Re: [PATCH manpages 1/2] modify_ldt.2: Overhaul the documentation

From: Michael Kerrisk (man-pages)
Date: Fri Jan 30 2015 - 07:18:38 EST


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@xxxxxxxxxxxxxx>
> ---
> 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@xxxxxxxxxxxxxxxxx), 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.

> +.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?

> +.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 ?

> +.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/
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/