lkml.org 
[lkml]   [2015]   [Jan]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
From
Date
SubjectRe: [PATCH manpages 1/2] modify_ldt.2: Overhaul the documentation
On Jan 30, 2015 8:18 AM, "Michael Kerrisk (man-pages)"
<mtk.manpages@gmail.com> wrote:
>
> Hi Andy,
>
> On 01/29/2015 10:47 PM, Andy Lutomirski wrote:
> > This clarifies the behavior and documents all four functions.
>
> Thanks! I've merged this in a branch, pending one or two questions below.
>
> > Signed-off-by: Andy Lutomirski <luto@amacapital.net>
> > ---
> > man2/modify_ldt.2 | 101 +++++++++++++++++++++++++++++++++++++++++-------------
> > 1 file changed, 78 insertions(+), 23 deletions(-)
> >
> > diff --git a/man2/modify_ldt.2 b/man2/modify_ldt.2
> > index d128664716c6..f3cc94d397b3 100644
> > --- a/man2/modify_ldt.2
> > +++ b/man2/modify_ldt.2
> > @@ -1,4 +1,5 @@
> > .\" Copyright (c) 1995 Michael Chastain (mec@duracef.shout.net), 22 July 1995.
> > +.\" Copyright (c) 2015 Andrew Lutomirski
> > .\"
> > .\" %%%LICENSE_START(GPLv2+_DOC_FULL)
> > .\" This is free documentation; you can redistribute it and/or
> > @@ -23,37 +24,43 @@
> > .\"
> > .TH MODIFY_LDT 2 2012-07-13 "Linux" "Linux Programmer's Manual"
> > .SH NAME
> > -modify_ldt \- get or set ldt
> > +modify_ldt \- get or set a per-process LDT entry
> > .SH SYNOPSIS
> > .nf
> > .B #include <sys/types.h>
> > .sp
> > .BI "int modify_ldt(int " "func" ", void *" "ptr" ", unsigned long " "bytecount" );
> > .fi
> > -
> > +.PP
> > .IR Note :
> > There is no glibc wrapper for this system call; see NOTES.
> > .SH DESCRIPTION
> > .BR modify_ldt ()
> > -reads or writes the local descriptor table (ldt) for a process.
> > -The ldt is a per-process memory management table used by the i386 processor.
> > -For more information on this table, see an Intel 386 processor handbook.
> > +reads or writes the local descriptor table (LDT) for a process. The LDT
> > +is an array of segment descriptors that can be referenced by user code.
> > +Linux allows processes to configure a per-process (actually per-mm) LDT.
> > +For more information about the LDT, see the Intel Software Developer's
> > +Manual or the AMD Architecture Programming Manual.
> > .PP
> > When
> > .I func
> > is 0,
> > .BR modify_ldt ()
> > -reads the ldt into the memory pointed to by
> > +reads the LDT into the memory pointed to by
> > .IR ptr .
> > The number of bytes read is the smaller of
> > .I bytecount
> > -and the actual size of the ldt.
> > +and the actual size of the LDT, although the kernel may act as though
> > +the LDT is padded with additional trailing zero bytes. On success,
> > +.BR modify_ldt ()
> > +will return the number of bytes read.
> > .PP
> > When
> > .I func
> > -is 1,
> > +is 1 or 0x11,
> > .BR modify_ldt ()
> > -modifies one ldt entry.
> > +modifies the LDT entry indicated by
> > +.I ptr\->entry_number.
> > .I ptr
> > points to a
> > .I user_desc
> > @@ -61,11 +68,6 @@ structure
> > and
> > .I bytecount
> > must equal the size of this structure.
> > -.\"
> > -.\" FIXME Should this page say something about func == 2 and func == 0x11?
> > -.\" In Linux 2.4, func == 2 returned "the default ldt"
> > -.\" In Linux 2.6, func == 2 is a nop, returning a zeroed out structure.
> > -.\" Linux 2.4 and 2.6 implement an operation for func == 0x11
> >
> > The
> > .I user_desc
> > @@ -89,12 +91,44 @@ struct user_desc {
> > .PP
> > In Linux 2.4 and earlier, this structure was named
> > .IR modify_ldt_ldt_s .
> > -.\" .PP
> > -.\" The ldt is specific for the calling process. Any attempts to change
> > -.\" the ldt to include the address space of another process or the kernel
> > -.\" will result in a segmentation violation when trying to access the memory
> > -.\" outside of the process address space. The memory protection is enforced
> > -.\" at the paging layer.
> > +.PP
> > +The
> > +.I contents
> > +field is the segment type (data, expand-down data, non-conforming code, or
> > +conforming code). The other fields match their descriptions in the
> > +CPU manual, although
> > +.BR modify_ldt ()
> > +cannot set the accessed bit.
>
> The "accessed bit" is mentioned here for the first time. Is this something
> described in the CPU Manual? If so, we better say that. As it is, I started
> hunting the rest of this man page for an explanation of this bit, without
> success.

Yes, it's in the CPU manual. Could we say "cannot set the
hardware-defined accessed bit"?

>
> > +.PP
> > +A
> > +.I user_desc
> > +is considered "empty" if
> > +.I read_exec_only
> > +and
> > +.I seg_not_present
> > +are set to 1 and all of the other fields are 0.
> > +An LDT entry can be cleared by setting it to an "empty"
> > +.I user_desc
> > +or, if
> > +.I func
> > +is 1, by setting both
> > +.I base
> > +and
> > +.I limit
> > +to 0.
> > +.PP
> > +A conforming code segment will be rejected if
> > +.I
> > +func
> > +is 1 or if
> > +.I seg_not_present
> > +is 0.
>
> It's not clear what a "conforming code segment is". Should some words
> be added here?

How about "conforming code segment (i.e. contents == 3)"?

>
> > +.PP
> > +When
> > +.I func
> > +is 2,
> > +.BR modify_ldt ()
> > +will read zeros. This appears to be a leftover from Linux 2.4.
> > .SH RETURN VALUE
> > On success,
> > .BR modify_ldt ()
> > @@ -119,19 +153,40 @@ or
> > is 1 and
> > .I bytecount
> > is not equal to the size of the structure
> > -.IR modify_ldt_ldt_s ,
> > +.IR user_desc ,
> > or
> > .I func
> > -is 1 and the new ldt entry has invalid values.
> > +is 1 or 0x11 and the new ldt entry has invalid values.
> > .TP
> > .B ENOSYS
> > .I func
> > -is neither 0 nor 1.
> > +is neither 0, 1, 2, nor 0x11.
> > .SH CONFORMING TO
> > This call is Linux-specific and should not be used in programs intended
> > to be portable.
> > +.SH BUGS
> > +On 64-bit kernels before Linux 3.19, one of the padding bits in
>
> Was that commit e30ab185c490e9a9381385529e0fd32f0a399495 ?

Yes.

It could be worth adding a note somewhere that 64-bit kernels define a
user_desc bit called "lm", but that its only effect is to interfere
with detection of "empty" descriptors on older kernels. It may be
further worth noting somewhere that it is not possible to use
modify_ldt(2) to install a long mode segment.

--Andy

>
> > +.I user_desc,
> > +if set, would prevent the descriptor from being considered empty.
> > .SH NOTES
> > Glibc does not provide a wrapper for this system call; call it using
> > .BR syscall (2).
> > +.PP
> > +.BR modify_ldt ()
> > +should not be used for thread-local storage, as it slows down context
> > +switches and only supports a limited number of threads. Threading libraries
> > +should use
> > +.BR set_thread_area (2)
> > +or
> > +.BR arch_prctl (2)
> > +instead, except on extremely old kernels that do not support those system
> > +calls.
> > +.PP
> > +The normal use for
> > +.BR modify_ldt (2)
> > +is to run legacy 16-bit or segmented 32-bit code. Not all kernels allow
> > +16-bit segments to be installed, however.
> > .SH SEE ALSO
> > +.BR set_thread_area (2),
> > +.BR arch_prctl (2),
> > .BR vm86 (2)
>
> Thanks,
>
> Michael
>
>
> --
> Michael Kerrisk
> Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
> Linux/UNIX System Programming Training: http://man7.org/training/


\
 
 \ /
  Last update: 2015-01-30 16:01    [W:0.069 / U:0.980 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site