There is a lot of unnecessary duplication of content of the seccomp
material in prctl(2) and seccomp(2). Trevor Woerner also noted that
there is an error in prctl(2), where it says that the filters
"are run in order until the first non-allow result is seen", which
contradicts the correct statement in seccomp(2) that *all* filters
are executed.
So, rewrite the seccomp material in prctl(2) to strip out most of
the content duplicated in seccomp(2), and replace the removed
text with statements deferring to to seccomp(2).
Reported-by: Trevor Woerner <twoerner@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Add some subsection (.SS) headings and paragraph breaks in
DESCRIPTION, to make the page more easily readable.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
glibc has tightened up its rules for replacing the memory
allocator. I went through the malloc man page and looked for how
it documented malloc() and related functions, and fixed
discrepancies with glibc malloc() documentation and/or
implementation. I also reorganized the portability discussion so
that portability issues can be seen more clearly.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Documentation/filesystems/sharedsubtree.txt has changed to
Documentation/filesystems/sharedsubtree.rst.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Especially the change to .rst format in the kernel Documentation/
tree has rendered many of the references in this manual page
obsolete. Fix them.
Reported-by: Vito Caputo <vcaputo@pengaru.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This makes it easier to compare this page to the standard,
to get more details about the rules between operators.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Unary operators are mentioned in C11::6.5.3, and casts are in
C11::6.5.4 (they are mentioned in order of precedence).
And from note 85 (in section 6.5) in that same C11 standard, major
subsections 6.5.X are sorted by precedence.
As an example (from Jakub), `sizeof(int)+1` is interpreted as
`(sizeof(int))+1`, and not `sizeof((int)+1)`.
I used C11 and not C18 (the latest) because at least in the draft
copy of C18 that I have, there are a few important typos in that
section, while the draft copy of C11 that I have is free of those
typos. And C11 and C18 are almost identical, with no major
changes to the language.
Reported-by: David Sletten <david.paul.sletten@gmail.com>
Cc: Jakub Wilk <jwilk@jwilk.net>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Zero in this case refers to literal constant 0 and not symbolic
constant B0.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
As noted by Jakub:
BTW, the exit_group.2 man page could use an update (possibly
by merging it into exit.2): it says that the "system
call is is equivalent to _exit(2) except that it terminates
not only the calling thread, but all threads in the calling
process's thread group", which isn't helpful these days.
Reported-by: Jakub Wilk <jwilk@jwilk.net>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The previous wording wasn't very explicit, leaving room for
believing that 'errno' may be 0 after returning EAI_SYSTEM.
Use a wording similar to other pages, for added consistency.
[mtk: edited commit message title; also, POSIX notes that
'errno' is set in this case.]
Reported-by: Cristian Morales Vega <christian.morales.vega@gmail.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Many times, this page use the terminology "mount point", where
"mount" would be better. A "mount point" is the location at which
a mount is attached. A "mount" is an association between a
filesystem and a mount point.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The correct terminology is "less privileged mount namespace"
(not "less privileged user namespace").
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The "Restrictions on mount namespaces" subsection belongs lower in
the page, following the discussion of concepts (e.g., shared
subtrees and propagation) that are discussed elsewhere in the page.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The previous commit injected a large block of text into a list,
separating one example in the previous list item from a
"continuation" in the following list item. repair that.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
For a long time, this manual page has had a brief discussion of
"locked" mounts, without clearly saying what this concept is, or
why it exists. Expand the discussion with an explanation of what
locked mounts are, why mounts are locked, and some examples of the
effect of locking.
Thanks to Christian Brauner for a lot of help in understanding
these details.
Reported-by: Christian Brauner <christian.brauner@ubuntu.com>
Acked-by: Christian Brauner <christian.brauner@ubuntu.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
These pages split out extra errors for some APIs into a separate
list. Probably, the pages are easier to ready if all errors are
combined into a single list.
Note that there still remain a few pages where the errors are
listed separately for different APIs. For the moment, it seems
best to leave those pages as is, since the error lists are
largely distinct in those pages.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
These split out errors into separate lists (perhaps per API,
perhaps "may" vs "shall", perhaps "Linux-specific" vs
standard(??)), but there's no good reason to do this. It makes
the error list harder to read, and is inconsistent with other
pages. So, combine the errors into a single list.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Mainly in preparation for the following patch on project IDs maps.
Add some words that will make the parallels between the rules for
updating uid_map and projid_map clearer.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Many times, these pages use the terminology "mount point", where
"mount" would be better. A "mount point" is the location at which
a mount is attached. A "mount" is an association between a
filesystem and a mount point.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Linux 5.8 adds STATX_MNT_ID and stx_mnt_id.
Add description to statx.2
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
From email with Christian Brauner:
>>>>>> int fd_tree = open_tree(-EBADF, source,
>>>>>> OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC |
>>>>>> AT_EMPTY_PATH | (recursive ? AT_RECURSIVE : 0));
>>>>>
>>>>> ???
>>>>> What is the significance of -EBADF here? As far as I can tell, it
>>>>> is not meaningful to open_tree()?
>>>>
>>>> I always pass -EBADF for similar reasons to [2]. Feel free to just use -1.
>>>
>>> ????
>>> But here, both -EBADF and -1 seem to be wrong. This argument
>>> is a dirfd, and so should either be a file descriptor or the
>>> value AT_FDCWD, right?
>>
>> [1]: In this code "source" is expected to be absolute. If it's not
>> absolute we should fail. This can be achieved by passing -1/-EBADF,
>> afaict.
>
> D'oh! Okay. I hadn't considered that use case for an invalid dirfd.
> (And now I've done some adjustments to openat(2),which contains a
> rationale for the *at() functions.)
>
> So, now I understand your purpose, but still the code is obscure,
> since
>
> * You use a magic value (-EBADF) rather than (say) -1.
> * There's no explanation (comment about) of the fact that you want
> to prevent relative pathnames.
>
> So, I've changed the code to use -1, not -EBADF, and I've added some
> comments to explain that the intent is to prevent relative pathnames.
> Okay?
Sounds good.
>
> But, there is still the meta question: what's the problem with using
> a relative pathname?
Nothing per se. Ok, you asked so it's your fault:
When writing programs I like to never use relative paths with AT_FDCWD
because. Because making assumptions about the current working directory
of the calling process is just too easy to get wrong; especially when
pivot_root() or chroot() are in play.
My absolut preference (joke intended) is to open a well-known starting
point with an absolute path to get a dirfd and then scope all future
operations beneath that dirfd. This already works with old-style
openat() and _very_ cautious programming but openat2() and its
resolve-flag space have made this **chef's kiss**.
If I can't operate based on a well-known dirfd I use absolute paths with
a -EBADF dirfd passed to *at() functions.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
From email:
>> Thanks. I made it "detached". Elsewhere, the page already explains
>> that a detached mount is one that:
>>
>> must have been created by calling open_tree(2) with the
>> OPEN_TREE_CLONE flag and it must not already have been
>> visible in the filesystem.
>>
>> Which seems a fine explanation.
>>
>> ????
>> But, just a thought... "visible in the filesystem" seems not quite accurate.
>> What you really mean I guess is that it must not already have been
>> /visible in the filesystem hierarchy/previously mounted/something else/,
>> right?
I suppose that I should have clarified that my main problem was
that you were using the word "filesystem" in a way that I find
unconventional/ambiguous. I mean, I normally take the term
"filesystem" to be "a storage system for folding files".
Here, you are using "filesystem" to mean something else, what
I might call like "the single directory hierarchy" or "the
filesystem hierarchy" or "the list of mount points".
> A detached mount is created via the OPEN_TREE_CLONE flag. It is a
> separate new mount so "previously mounted" is not applicable.
> A detached mount is _related_ to what the MS_BIND flag gives you with
> mount(2). However, they differ conceptually and technically. A MS_BIND
> mount(2) is always visible in the fileystem when mount(2) returns, i.e.
> it is discoverable by regular path-lookup starting within the
> filesystem.
>
> However, a detached mount can be seen as a split of MS_BIND into two
> distinct steps:
> 1. fd_tree = open_tree(OPEN_TREE_CLONE): create a new mount
> 2. move_mount(fd_tree, <somewhere>): attach the mount to the filesystem
>
> 1. and 2. together give you the equivalent of MS_BIND.
> In between 1. and 2. however the mount is detached. For the kernel
> "detached" means that an anonymous mount namespace is attached to it
> which doen't appear in proc and has a 0 sequence number (Technically,
> there's a bit of semantical argument to be made that "attached" and
> "detached" are ambiguous as they could also be taken to mean "does or
> does not have a parent mount". This ambiguity e.g. appears in
> do_move_mount(). That's why the kernel itself calls it an "anonymous
> mount". However, an OPEN_TREE_CLONE-detached mount of course doesn't
> have a parent mount so it works.).
>
> For userspace it's better to think of detached and attached in terms of
> visibility in the filesystem or in a mount namespace. That's more
> straightfoward, more relevant, and hits the target in 90% of the cases.
>
> However, the better and clearer picture is to say that a
> OPEN_TREE_CLONE-detached mount is a mount that has never been
> move_mount()ed. Which in turn can be defined as the detached mount has
> never been made visible in a mount namespace. Once that has happened the
> mount is irreversibly an attached mount.
>
> I keep thinking that maybe we should just say "anonymous mount"
> everywhere. So changing the wording to:
I'm not against the word "detached". To user space, I think it is a
little more meaningful than "anonymous". For the moment, I'll stay with
"detached", but if you insist on "anonymous", I'll probably change it.
> [...]
> EINVAL The mount that is to be ID mapped is not an anonymous mount;
> that is, the mount has already been visible in a mount namespace.
I like that text *a lot* better! Thanks very much for suggesting
wordings. It makes my life much easier.
I've made the text:
EINVAL The mount that is to be ID mapped is not a detached
mount; that is, the mount has not previously been
visible in a mount namespace.
> [...]
> The mount must be an anonymous mount; that is, it must have been
> created by calling open_tree(2) with the OPEN_TREE_CLONE flag and it
> must not already have been visible in a mount namespace, i.e. it must
> not have been attached to the filesystem hierarchy with syscalls such
> as move_mount() syscall.
And that too! I've made the text:
• The mount must be a detached mount; that is, it must have
been created by calling open_tree(2) with the
OPEN_TREE_CLONE flag and it must not already have been
visible in a mount namespace. (To put things another way:
the mount must not have been attached to the filesystem
hierarchy with a system call such as move_mount(2).)
Reported-by: Christian Brauner <christian.brauner@ubuntu.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
From email with Christian Braner:
> [1]: In this code "source" is expected to be absolute. If it's not
> absolute we should fail. This can be achieved by passing -1/-EBADF,
> afaict.
D'oh! Okay. I hadn't considered that use case for an invalid dirfd.
(And now I've done some adjustments to openat(2),which contains a
rationale for the *at() functions.)
So, now I understand your purpose, but still the code is obscure,
since
* You use a magic value (-EBADF) rather than (say) -1.
* There's no explanation (comment about) of the fact that you want
to prevent relative pathnames.
So, I've changed the code to use -1, not -EBADF, and I've added some
comments to explain that the intent is to prevent relative pathnames.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Make the description of the EBADF error for invalid 'dirfd' more
uniform. In particular, note that the error only occurs when the
pathname is relative, and that it occurs when the 'dirfd' is
neither valid *nor* has the value AT_FDCWD.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
In particular, specifying an invalid file descriptor number
in 'dirfd' can be used as a check that 'pathname' is absolute.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Kir Kolyshkin made a start, but I think much more needs to
be said...
Reviewed-by: Serge E. Hallyn <serge@hallyn.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
From an email conversation with Alexis:
Hello Alexis,
On 8/6/21 7:06 PM, Alexis Wilke wrote:
> Hi guys,
>
> The pthread_setname_np(3) manual page has an example where the second
> argument is used to get a size of the thread name.
>
> https://man7.org/linux/man-pages/man3/pthread_setname_np.3.html#EXAMPLES
>
> The current code:
>
> rc = pthread_getname_np(thread, thread_name,
> (argc > 2) ? atoi(argv[1]) : NAMELEN);
>
> The suggested code:
>
> rc = pthread_getname_np(thread, thread_name,
> (argc > 2) ? atoi(argv[2]) : NAMELEN);
I agree that there's a problem, but I think we could go even simpler:
rc = pthread_getname_np(thread, thread_name, NAMELEN);
> I'm thinking that maybe the author meant to compute the length like so:
>
> rc = pthread_getname_np(thread, thread_name,
> (argc > 2) ? strlen(argv[1]) + 1 :
> NAMELEN);
>
> But I think that the atoi() points to using argv[2] as a number
> representing the length.
>
> (Of course, it should be tested against NAMELEN as a maximum, but I
> understand that examples do not always show how to verify each possible
> error).
I imagine that the author's intention was to allow the user to do
experiments where argv[2] specified a number less than NAMELEN,
in order to see the resulting ERANGE error. But, that experiment
is of limited value, and complicates the code unnecessarily, IMO,
so that's why I made the change above.
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
Reported-by: Alexis Wilke <alexis@m2osw.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Phrases such as "In the new mount API" will date fast. Remove it.
Also:
* Make it clear that MOUNT_ATTR__ATIME expresses a bit field.
* Replace 'enum' with 'enumeration'.
* Clarify what is meant by "partially" set MOUNT_ATTR__ATIME.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
These types are already well described in mount_namespaces(7);
indeed, much of the text from that page seems to have just been
cut and pasted into this page! Simply referring the reader to
mount_namespaces(7) is sufficient.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Point out that this field can have the value zero, meaning
no change. And avoid discussions of 'enum', and simply say
that otherwise the field has one of the MS_* values.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Reported-by: Acked-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Having this discussion under DESCRIPTION clutters that section,
and has the effect of burying the discussion of propagation. Move
the discussion to NOTES, to make the page more readable.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
- Change some instances of "-" to "\"
- Use C99 style (declare variables nearer use in code)
- Add a bit of white space
- Remove one 'const...const' added by Alex that caused
compiler warnings
- Use "reverse Christmas tree" form for declarations in main()
- Other minor changes
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
We don't really need ext4(5) and xfs(5) here. They provide
no further info that is directly relevant to the reader of
mount_setattr(2).
clone3(2) isn't necessary because it is the same page as clone(2).
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
- Fix SYNOPSIS to fit in 78 columns
Also, we don't show when an include is included for a specific type,
unless that header is included _only_ for the type,
or there might be confusion (e.g., termios).
Instead, that type should be documented in system_data_types(7),
with a link page mount_attr-struct(3).
- Fix references to mount_setattr(). See man-pages(7):
Any reference to the subject of the current manual page should be writ‐
ten with the name in bold followed by a pair of parentheses in Roman
(normal) font. For example, in the fcntl(2) man page, references to
the subject of the page would be written as: fcntl(). The preferred
way to write this in the source file is:
.BR fcntl ()
- Fix line breaks according to semantic newline rules (and add some commas)
- Fix wrong usage of .IR when .RI should have been used
- Fix formatting of variable part in FOO<number>:
- Make italic the variable part (as groff_man(7) recommends)
- Remove <>
- Use syntax recommended by G. Branden Robinson (groff)
- Fix unnecessary uses of .BR or .IR when .B or .I would suffice
- Fix formatting of punctuation
In some cases, it was in italics or bold, and it should always be in roman.
- Use uppercase to begin text, even in bullet points, since those were
multi-sentence.
- Simplify usage of .RS/.RE in combination with .IP
- s/fat/FAT/ as fs(7) does
- Slightly reword some sentences for consistency
- Use Linux-specific for consistency with other pages (in VERSIONS)
- EXAMPLES: Place the return type in a line of its own (as in other pages)
- Fix alignment of code
- Replace unnecessary use of the GNU extension ({}) by do {} while (0)
In that case, there was no return value (moreover, it's a noreturn).
- Break complex declaration lines into a line for each variable
The variables were being initialized, some to non-zero values,
so for clarity, a line for each one seems more appropriate.
- Add const to pointers when possible
- s/\\/\e/
- Remove unmatched groff commands
Cc: Christian Brauner <brauner@kernel.org>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Note the use of FUTEX_CLOCK_REALTIME for selecting the clock,
and eliminate repetition of details already covered in the
description of FUTEX_LOCK_PI.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
FUTEX_LOCK_PI2 is a new futex operation which was recently introduced into the
Linux kernel. It works exactly like FUTEX_LOCK_PI. However, it has support for
selectable clocks for timeouts. By default CLOCK_MONOTONIC is used. If
FUTEX_CLOCK_REALTIME is specified then the timeout is measured against
CLOCK_REALTIME.
This new operation addresses an inconsistency in the futex interface:
FUTEX_LOCK_PI only works with timeouts based on CLOCK_REALTIME in contrast to
all the other PI operations.
Document the FUTEX_LOCK_PI2 command.
Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
- Move example program to a new EXAMPLES section
- Invert logic in the handler to have the failure in the
conditional path, and the success out of any conditionals.
- Use NULL, EXIT_SUCCESS, and EXIT_FAILURE instead of magic numbers
- Separate declarations from code
- Put function return type on its own line
- Put function opening brace on its line
Cc: Peter Collingbourne <pcc@google.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
See https://bugzilla.kernel.org/show_bug.cgi?id=212385
some/path/dir/ is not always the same as some/path/dir/:
$ mkdir u
$ rmdir u/.
rmdir: failed to remove 'u/.': Invalid argument
$ rmdir u
$
The text in POSIX.1-2018 Section 4.13 ("Pathname Resolution")
is helpful in pointing to a better wording.
Reported-by: Askar Safin <safinaskar@mail.ru>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Emanuele Torre via linux-man@:
[
I was reading the man page for ldd(1)[1]; and I read this in the first
paragraph of the DECRIPTION section:
ldd prints the shared objects (shared libraries) required by each
program or shared object specified on the command line. An
example of its use and output (using sed(1) to trim leading white
space for readability in this page) is the following:
$ ldd /bin/ls | sed 's/^ */ /'
linux-vdso.so.1 (0x00007ffcc3563000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f87e5459000)
libcap.so.2 => /lib64/libcap.so.2 (0x00007f87e5254000)
libc.so.6 => /lib64/libc.so.6 (0x00007f87e4e92000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f87e4c22000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f87e4a1e000)
/lib64/ld-linux-x86-64.so.2 (0x00005574bf12e000)
libattr.so.1 => /lib64/libattr.so.1 (0x00007f87e4817000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f87e45fa000)
This is a little confusing though since that sed(1) command does not
seem to work. (and also potentially misleading for someone who is trying
figure out how to parse ldd(1)'s output.)
ldd(1) prepends a TAB character (0x09) to each line, not spaces:
$ ldd /bin/ls | xxd | head -1
00000000: 096c 696e 7578 2d76 6473 6f2e 736f 2e31 .linux-vdso.so.1
I read ldd(1)'s source code[2] (it is part of glibc) and it seems to be
a bash script that tries to use different rtld programs ( ld.so(8) )
from an RTLDLIST.
Those, on my system, are:
* /usr/lib/ld-linux.so.2
* /usr/lib64/ld-linux-x86-64.so.2
* /usr/libx32/ld-linux-x32.so.2
And they all seem to also be part of glibc.
I have tried to follow the git history of glibc to see when the switch
from spaces to the TAB character occured, but, to me, it seems like
glibc.git/elf/rtld.c has always used '\t'; at since
6a76c115150318eae5d02eca76f2fc03be7bd029[3] (358th commit since glibc
started using the git repository repository - Nov 18th 1995): before
that commit there are not any results for `git grep '\\t'` in the elf
directory and I did not investigate further.
Still, at the time of that commit, glibc did not seem to have an ldd(1)
utility.
Perhaps the man page is old and its original author was using and
documenting an ldd(1) utility that was not part of glibc when he was
writing it.
Anyhow, since I think that sed(1) command will not work on any system
that uses, at least, the most recent version of glibc (because lld(1)
and the ld.so(8) programs it depends on are all part of glibc), I think
that that example should be changed to avoid confusions.
The output format of ldd(1) does not seem to be clearly defined, so I
think this would be a good option:
$ ldd /bin/ls | sed 's/^[[:space:]]*/ /'
NB: ^\s* should also work on most GNU/Linux systems, but \s is
non-standard or documented so I don not suggest using it in the man
page.
Another option could be to remove "the pipe to sed(1)" part and the note
in parentheses that explains why it was used by the original author.
Cheers.
emanuele6
[1]: https://man7.org/linux/man-pages/man1/ldd.1.html
[2]: https://sourceware.org/git/?p=glibc.git;a=blob;f=elf/ldd.bash.in;h=ba736464ac5e4a9390b1b6a39595035238250232;hb=5188a9d0265cc6f7235a8af1d31ab02e4a24853d
[3]: https://sourceware.org/git/?p=glibc.git;a=commit;h=6a76c115150318eae5d02eca76f2fc03be7bd029
///////
$ uname -a
Linux t420 5.10.54-1-lts #1 SMP Wed, 28 Jul 2021 15:05:20 +0000
x86_64 GNU/Linux
$ pacman -Qo ldd
/usr/bin/ldd is owned by glibc 2.33-5
$ pacman -Qo /usr/share/man/man1/ldd.1.gz
/usr/share/man/man1/ldd.1.gz is owned by man-pages 5.12-2
$ pacman -Qo /usr/lib/ld-linux.so.2
/usr/lib/ld-linux.so.2 is owned by lib32-glibc 2.33-5
$ pacman -Qo /usr/lib64/ld-linux-x86-64.so.2
/usr/lib/ld-linux-x86-64.so.2 is owned by glibc 2.33-5
$ pacman -F /usr/libx32/ld-linux-x32.so.2 || echo not available on arch linux.
not available on arch linux.
]
Reported-by: EmanueleTorre <torreemanuele6@gmail.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: James O. D. Hunt <jamesodhunt@gmail.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Explain that `optstring` cannot contain a semi-colon (`;`)
character.
[mtk: verified with a small test program; see also posix/getopt.c
in the glibc sources:
if (temp == NULL || c == ':' || c == ';')
{
if (print_errors)
fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c);
d->optopt = c;
return '?';
}
]
Also explain that `optstring` can include `+` as an option
character, possibly in addition to that character being used as
the first character in `optstring` to denote `POSIXLY_CORRECT`
behaviour.
[mtk: verified with a small test program.]
Test program below. Example runs:
$ ./a.out -+
opt = 43 (+); optind = 2
Got plus
$ ./a.out -';'
./a.out: invalid option -- ';'
opt = 63 (?); optind = 2; optopt = 59 (;)
Unrecognized option (-;)
Usage: ./a.out [-p arg] [-x]
Signed-off-by: James O. D. Hunt <jamesodhunt@gmail.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---
#include <ctype.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define printable(ch) (isprint((unsigned char) ch) ? ch : '#')
static void /* Print "usage" message and exit */
usageError(char *progName, char *msg, int opt)
{
if (msg != NULL && opt != 0)
fprintf(stderr, "%s (-%c)\n", msg, printable(opt));
fprintf(stderr, "Usage: %s [-p arg] [-x]\n", progName);
exit(EXIT_FAILURE);
}
int
main(int argc, char *argv[])
{
int opt, xfnd;
char *pstr;
xfnd = 0;
pstr = NULL;
while ((opt = getopt(argc, argv, "p:x+;")) != -1) {
printf("opt =%3d (%c); optind = %d", opt, printable(opt), optind);
if (opt == '?' || opt == ':')
printf("; optopt =%3d (%c)", optopt, printable(optopt));
printf("\n");
switch (opt) {
case 'p': pstr = optarg; break;
case 'x': xfnd++; break;
case ';': printf("Got semicolon\n"); break;
case '+': printf("Got plus\n"); break;
case ':': usageError(argv[0], "Missing argument", optopt);
case '?': usageError(argv[0], "Unrecognized option", optopt);
default:
printf("Unexpected case in switch()\n");
exit(EXIT_FAILURE);
}
}
if (xfnd != 0)
printf("-x was specified (count=%d)\n", xfnd);
if (pstr != NULL)
printf("-p was specified with the value \"%s\"\n", pstr);
if (optind < argc)
printf("First nonoption argument is \"%s\" at argv[%d]\n",
argv[optind], optind);
exit(EXIT_SUCCESS);
}
Do not include unused (and incompatible) header file termios.h and
include required header files for puts() and close() functions.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
SPARC is special, it does not have Bnnn constants for baud rates above
2000000. Instead it defines 4 Bnnn constants with smaller baud rates.
This difference between SPARC and non-SPARC architectures is present in
both glibc API (termios.h) and also kernel ioctl API (asm/termbits.h).
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Format variable parts of words referring to a group of identifiers
in italics, following groff_man(7) recommendations.
Also srcfix surrounding uses of \f escape sequences to use macros
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
These baud-rate macro constants are defined in bits/termios.h and are
already supported.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Saw this while preparing the "switch to \~" change Alex invited.
Signed-off-by: G. Branden Robinson <g.branden.robinson@gmail.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
After a patch proposal from наб triggered by concerns that, when
talking about PIPE_BUF, pipe(7) explicitly mentions write(2) but
not writev(2), I've concluded that the reference in writev(2) to
pipe(7) is not needed (mea culpa; I added that text), and I think
the text in pipe(7) could be written to be closer to the POSIX
spec, which doesn't talk about "write() calls", but simply about
"writes".
Reported-by: наб <nabijaczleweli@nabijaczleweli.xyz>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Mainly: I generally don't want us to be including URLs to mailing
list discussions in a manual page. Either, the issue in the
discussion is worth writing up in the manual page (so that
the reader doesn't have to look elsewhere), or the details
are less important, in which case it is sufficient to note the
existence of the bug. I think this is an example of the latter.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The correct kernel version seems to 5.11, not 5.10:
$ git describe --contains d0e3fc69d00d
v5.11-rc1~76^2~251
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Christophe Leroy via Bugzilla:
https://bugzilla.kernel.org/show_bug.cgi?id=213421
[
In ppc32 functions section, the Y2038 compliant function
__kernel_clock_gettime64() is missing.
It was added by commit d0e3fc69d00d
("powerpc/vdso: Provide __kernel_clock_gettime64() on vdso32")
]
.../linux$ git describe d0e3fc69d00d
v5.10-rc2-76-gd0e3fc69d00d
Reported-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
As pointed out by Nora, the example shown in the manual
page already demonstrates that the pathname is not absolute!
Reported-by: Nora Platiel <nplatiel@gmx.us>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Remove duplicated word.
Signed-off-by: Jakub Wilk <jwilk@jwilk.net>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Fix a typo in the documentation of using fallocate to allocate shared
blocks. The flag FALLOC_FL_UNSHARE should instead be documented as
FALLOC_FL_UNSHARE_RANGE.
Fixes: 63a599c657 ("man2/fallocate.2: Document behavior with shared blocks")
Signed-off-by: Dan Robertson <dan@dlrobertson.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Alan:
[
The on-line copy of the manual page "posixoptions(7)" dated
2018-04-30 has an entry for "getcwd()" in the section headed
"XSI - _XOPEN_LEGACY - _SC_XOPEN_LEGACY".
I believe that entry should be "getwd()" as that is the API call
which was present in X/Open-6 but withdrawn in X/Open-7.
]
mtk: confirmed by reviewing the table ("Removed Functions and
Symbols in Issue 7") at the end of Section B.1.1 on page
3564 of IEEE Std 1003.1, 2016 Edition.
Reported-by: Alan Peakall <Alan.Peakall@helpsystems.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
See https://bugzilla.kernel.org/show_bug.cgi?id=213419
ppc/32 and ppc/64 sections both have the following note:
The CLOCK_REALTIME_COARSE and CLOCK_MONOTONIC_COARSE clocks are
not supported by the __kernel_clock_getres and
__kernel_clock_gettime interfaces; the kernel falls back to the
real system call
This note has been wrong from quite some time now, since commit
654abc69ef2e ("powerpc/vdso32: Add support for
CLOCK_{REALTIME/MONOTONIC}_COARSE") and commit
5c929885f1bb ("powerpc/vdso64: Add support for
CLOCK_{REALTIME/MONOTONIC}_COARSE")
Reported-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Since commit ee81d7e418, the flags list has been (only) above, not
below, these references.
(The flags table was added even before that, in commit 0b497138b9
("namespaces.7: Add table of namespaces to top of page"))
Fixes: ee81d7e418 ("namespaces.7: Include manual page references in the summary table of namespace types")
Signed-off-by: Štěpán Němec <stepnem@gmail.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Correct function signature by adding missing parenthesis.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
I regularly get mildly lost in this table (and, indeed, didn't realise
it had two columns the first few times I used it to look at something
from the left column) ‒ separating the two columns improves clarity,
and makes which soup of numbers belongs to which character
much more obvious
Other encodings don't need this as they don't use double-columnated
tables
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The recv.2 misspelled `SO_EE_OFFENDER` to `SOCK_EE_OFFENDER`.
This patch fix this typo.
Signed-off-by: kXuan <kxuanobj@gmail.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The file being referred to no longer exists, as it was moved to
*.rst first (commit 20a78ae9ed297f2) and then to under
admin-guide (commit bf6b7a742e3f82b). Both those commits
are from 2019 (Linux 5.3).
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Using mount flag `MS_NOSUID` also affects SELinux domain transitions but
this has not been documented well.
Signed-off-by: Topi Miettinen <toiwoton@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
With a simple backslash, '\0' ended up as ' ' in the man output.
Reported-by: Štěpán Němec <stepnem@gmail.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
No implementation or spec requires *n to be 0 to allocate a new buffer:
* musl checks for !*lineptr
(and sets *n=0 for later allocations)
* glibc checks for !*lineptr || !*n
(but only because it allocates early)
* NetBSD checks for !*lineptr
(and sets *n=0 for later allocations)
(but specifies *n => mlen(*lineptr) >= *n as a precondition,
to which this appears to be an exception)
* FreeBSD checks for !*lineptr and sets *n=0
(and specifies !*lineptr as sufficient)
* Lastly, POSIX.1-2017 specifies:
> If *n is non-zero, the application shall ensure that *lineptr
> either points to an object of size at least *n bytes,
> or is a null pointer.
The new wording matches POSIX, even if it arrives at the point slightly
differently
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Don't document includes that provide types; only those that
provide prototypes and constants.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The types that need <sys/types.h> are better documented in
system_data_types(7). Let's keep only the includes for the
prototypes and the constants.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
'struct iovec' is defined in <bits/types/struct_iovec.h>,
which is included by <sys/io.h>, but it is also included by
<bits/fcntl-linux.h>, which is in the end included by <fcntl.h>.
Given that we already include <fcntl.h>, we don't need any more
includes.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
'struct utimbuf' is provided by <utime.h>.
There's no need for <sys/types.h>.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
<sys/types.h> makes no sense for a function that only uses 'int'.
The flags used by this function are provided by <fcntl.h>
(or others), but not by <linux/userfaultfd.h>.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
'mode_t', which is the only reason this might have been ever
needed, is provided by <sys/stat.h> since POSIX.1-2001.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
'off_t', which is the only reason this might have been ever
needed, is provided by <unistd.h> since POSIX.1-2001.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
There seems to be no reason to include <unistd.h>.
<sys/swap.h> already provides both the function prototypes and the
SWAP_* constants.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
<unistd.h> doesn't seem to be needed:
AT_* constants come from <fcntl.h>
STATX_* constants come from <sys/stat.h>
'struct statx' comes from <sys/stat.h>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Remove <sys/types.h>; ffix too
<sys/types.h> is only needed for 'struct stat'.
That is better documented in system_data_types(7).
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
A function declarator with empty parentheses, which is not a
prototype, is an obsolescent feature of C (See C17 6.11.6.1), and
doesn't mean 0 parameters, but instead that no information about
the parameters is provided (See C17 6.5.2.2).
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
It's only needed for getting 'mode_t'.
But that type is better documented in system_data_types(7).
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Doing so decreases the degree to which text is indented, and
thus avoids short, poorly wrapped lines.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Quoting Jann Horn:
[[
As discussed at
<https://lore.kernel.org/r/CAG48ez0m4Y24ZBZCh+Tf4ORMm9_q4n7VOzpGjwGF7_Fe8EQH=Q@mail.gmail.com>,
we need to re-check checkNotificationIdIsValid() after reading remote
memory but before using the read value in any way. Otherwise, the
syscall could in the meantime get interrupted by a signal handler, the
signal handler could return, and then the function that performed the
syscall could free() allocations or return (thereby freeing buffers on
the stack).
In essence, this pread() is (unavoidably) a potential use-after-free
read; and to make that not have any security impact, we need to check
whether UAF read occurred before using the read value. This should
probably be called out elsewhere in the manpage, too...
Now, of course, **reading** is the easy case. The difficult case is if
we have to **write** to the remote process... because then we can't
play games like that. If we write data to a freed pointer, we're
screwed, that's it. (And for somewhat unrelated bonus fun, consider
that /proc/$pid/mem is originally intended for process debugging,
including installing breakpoints, and will therefore happily write
over "readonly" private mappings, such as typical mappings of
executable code.)
So, uuuuh... I guess if anyone wants to actually write memory back to
the target process, we'd better come up with some dedicated API for
that, using an ioctl on the seccomp fd that magically freezes the
target process inside the syscall while writing to its memory, or
something like that? And until then, the manpage should have a big fat
warning that writing to the target's memory is simply not possible
(safely).
]]
and
<https://lore.kernel.org/r/CAG48ez0m4Y24ZBZCh+Tf4ORMm9_q4n7VOzpGjwGF7_Fe8EQH=Q@mail.gmail.com>:
[[
The second bit of trouble is that if the supervisor is so oblivious
that it doesn't realize that syscalls can be interrupted, it'll run
into other problems. Let's say the target process does something like
this:
int func(void) {
char pathbuf[4096];
sprintf(pathbuf, "/tmp/blah.%d", some_number);
mount("foo", pathbuf, ...);
}
and mount() is handled with a notification. If the supervisor just
reads the path string and immediately passes it into the real mount()
syscall, something like this can happen:
target: starts mount()
target: receives signal, aborts mount()
target: runs signal handler, returns from signal handler
target: returns out of func()
supervisor: receives notification
supervisor: reads path from remote buffer
supervisor: calls mount()
but because the stack allocation has already been freed by the time
the supervisor reads it, the supervisor just reads random garbage, and
beautiful fireworks ensue.
So the supervisor *fundamentally* has to be written to expect that at
*any* time, the target can abandon a syscall. And every read of remote
memory has to be separated from uses of that remote memory by a
notification ID recheck.
And at that point, I think it's reasonable to expect the supervisor to
also be able to handle that a syscall can be aborted before the
notification is delivered.
]]
Reported-by: Jann Horn <jannh@google.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
- Rename the function that does the SECCOMP_IOCTL_NOTIF_ID_VALID
check.
- Make that function return a 'bool' rather than terminating the
process.
- Use that return value in the calling function.
- Rework/improve various related comments.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
pidfd_open(2) and pidfd_getfd(2) presumably have use cases
with the user-space notification feature.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
According to Tycho Andersen, he had no particular use case
in mind when building this detail into the API.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The seccomp user-space notification feature can cause changes in
the semantics of SA_RESTART with respect to system calls that
would never normally be restarted. Point the reader to the page
that provide further details.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
And, as noted by Jann Horn, note how the user-space notification
mechanism causes a small breakage in the user-space API with
respect to nonrestartable system calls.
====
From the email discussion with Jann Horn
> >> So, I partially demonstrated what you describe here, for two example
> >> system calls (epoll_wait() and pause()). But I could not exactly
> >> demonstrate things as I understand you to be describing them. (So,
> >> I'm not sure whether I have not understood you correctly, or
> >> if things are not exactly as you describe them.)
> >>
> >> Here's a scenario (A) that I tested:
> >>
> >> 1. Target installs seccomp filters for a blocking syscall
> >> (epoll_wait() or pause(), both of which should never restart,
> >> regardless of SA_RESTART)
> >> 2. Target installs SIGINT handler with SA_RESTART
> >> 3. Supervisor is sleeping (i.e., is not blocked in
> >> SECCOMP_IOCTL_NOTIF_RECV operation).
> >> 4. Target makes a blocking system call (epoll_wait() or pause()).
> >> 5. SIGINT gets delivered to target; handler gets called;
> >> ***and syscall gets restarted by the kernel***
> >>
> >> That last should never happen, of course, and is a result of the
> >> combination of both the user-notify filter and the SA_RESTART flag.
> >> If one or other is not present, then the system call is not
> >> restarted.
> >>
> >> So, as you note below, the UAPI gets broken a little.
> >>
> >> However, from your description above I had understood that
> >> something like the following scenario (B) could occur:
> >>
> >> 1. Target installs seccomp filters for a blocking syscall
> >> (epoll_wait() or pause(), both of which should never restart,
> >> regardless of SA_RESTART)
> >> 2. Target installs SIGINT handler with SA_RESTART
> >> 3. Supervisor performs SECCOMP_IOCTL_NOTIF_RECV operation (which
> >> blocks).
> >> 4. Target makes a blocking system call (epoll_wait() or pause()).
> >> 5. Supervisor gets seccomp user-space notification (i.e.,
> >> SECCOMP_IOCTL_NOTIF_RECV ioctl() returns
> >> 6. SIGINT gets delivered to target; handler gets called;
> >> and syscall gets restarted by the kernel
> >> 7. Supervisor performs another SECCOMP_IOCTL_NOTIF_RECV operation
> >> which gets another notification for the restarted system call.
> >>
> >> However, I don't observe such behavior. In step 6, the syscall
> >> does not get restarted by the kernel, but instead returns -1/EINTR.
> >> Perhaps I have misconstructed my experiment in the second case, or
> >> perhaps I've misunderstood what you meant, or is it possibly the
> >> case that things are not quite as you said?
>
> Thanks for the code, Jann (including the demo of the CLONE_FILES
> technique to pass the notification FD to the supervisor).
>
> But I think your code just demonstrates what I described in
> scenario A. So, it seems that I both understood what you
> meant (because my code demonstrates the same thing) and
> also misunderstood what you said (because I thought you
> were meaning something more like scenario B).
Ahh, sorry, I should've read your mail more carefully. Indeed, that
testcase only shows scenario A. But the following shows scenario B...
[Below, two pieces of code from Jann, with a lot of
cosmetic changes by mtk.]
====
[And from a follow-up in the same email thread:]
> If userspace relies on non-restarting behavior, it should be using
> something like epoll_pwait(). And that stuff only unblocks signals
> after we've already past the seccomp checks on entry.
Thanks for elaborating that detail, since as soon as you talked
about "enlarging a preexisting race" above, I immediately wondered
sigsuspend(), pselect(), etc.
(Mind you, I still wonder about the effect on system calls that
are normally nonrestartable because they have timeouts. My
understanding is that the kernel doesn't restart those system
calls because it's impossible for the kernel to restart the call
with the right timeout value. I wonder what happens when those
system calls are restarted in the scenario we're discussing.)
Anyway, returning to your point... So, to be clear (and to
quickly remind myself in case I one day reread this thread),
there is not a problem with sigsuspend(), pselect(), ppoll(),
and epoll_pwait() since:
* Before the syscall, signals are blocked in the target.
* Inside the syscall, signals are still blocked at the time
the check is made for seccomp filters.
* If a seccomp user-space notification event kicks, the target
is put to sleep with the signals still blocked.
* The signal will only get delivered after the supervisor either
triggers a spoofed success/failure return in the target or the
supervisor sends a CONTINUE response to the kernel telling it
to execute the target's system call. Either way, there won't be
any restarting of the target's system call (and the supervisor
thus won't see multiple notifications).
====
Scenario A
$ ./seccomp_unotify_restart_scen_A
C: installed seccomp: fd 3
C: woke 1 waiters
P: child installed seccomp fd 3
C: About to call pause(): Success
P: going to send SIGUSR1...
C: sigusr1_handler handler invoked
P: about to terminate
C: got pdeath signal on parent termination
C: about to terminate
/* Modified version of code from Jann Horn */
#define _GNU_SOURCE
#include <stdio.h>
#include <signal.h>
#include <err.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sched.h>
#include <stddef.h>
#include <limits.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/prctl.h>
#include <linux/seccomp.h>
#include <linux/filter.h>
#include <linux/futex.h>
struct {
int seccomp_fd;
} *shared;
static void
sigusr1_handler(int sig, siginfo_t * info, void *uctx)
{
printf("C: sigusr1_handler handler invoked\n");
}
static void
sigusr2_handler(int sig, siginfo_t * info, void *uctx)
{
printf("C: got pdeath signal on parent termination\n");
printf("C: about to terminate\n");
exit(0);
}
int
main(void)
{
setbuf(stdout, NULL);
/* Allocate memory that will be shared by parent and child */
shared = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_SHARED, -1, 0);
if (shared == MAP_FAILED)
err(1, "mmap");
shared->seccomp_fd = -1;
/* glibc's clone() wrapper doesn't support fork()-style usage */
/* Child process and parent share file descriptor table */
pid_t child = syscall(__NR_clone, CLONE_FILES | SIGCHLD,
NULL, NULL, NULL, 0);
if (child == -1)
err(1, "clone");
/* CHILD */
if (child == 0) {
/* don't outlive the parent */
prctl(PR_SET_PDEATHSIG, SIGUSR2);
if (getppid() == 1)
exit(0);
/* Install seccomp filter */
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
struct sock_filter insns[] = {
BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
offsetof(struct seccomp_data, nr)),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_pause, 0, 1),
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
};
struct sock_fprog prog = {
.len = sizeof(insns) / sizeof(insns[0]),
.filter = insns
};
int seccomp_ret = syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER,
SECCOMP_FILTER_FLAG_NEW_LISTENER, &prog);
if (seccomp_ret < 0)
err(1, "install");
printf("C: installed seccomp: fd %d\n", seccomp_ret);
/* Place the notifier FD number into the shared memory */
__atomic_store(&shared->seccomp_fd, &seccomp_ret,
__ATOMIC_RELEASE);
/* Wake the parent */
int futex_ret =
syscall(__NR_futex, &shared->seccomp_fd, FUTEX_WAKE,
INT_MAX, NULL, NULL, 0);
printf("C: woke %d waiters\n", futex_ret);
/* Establish SA_RESTART handler for SIGUSR1 */
struct sigaction act = {
.sa_sigaction = sigusr1_handler,
.sa_flags = SA_RESTART | SA_SIGINFO
};
if (sigaction(SIGUSR1, &act, NULL))
err(1, "sigaction");
struct sigaction act2 = {
.sa_sigaction = sigusr2_handler,
.sa_flags = 0
};
if (sigaction(SIGUSR2, &act2, NULL))
err(1, "sigaction");
/* Make a blocking system call */
perror("C: About to call pause()");
pause();
perror("C: pause returned");
exit(0);
}
/* PARENT */
/* Wait for futex wake-up from child */
int futex_ret = syscall(__NR_futex, &shared->seccomp_fd, FUTEX_WAIT,
-1, NULL, NULL, 0);
if (futex_ret == -1 && errno != EAGAIN)
err(1, "futex wait");
/* Get notification FD from the child */
int fd = __atomic_load_n(&shared->seccomp_fd, __ATOMIC_ACQUIRE);
printf("\tP: child installed seccomp fd %d\n", fd);
sleep(1);
printf("\tP: going to send SIGUSR1...\n");
kill(child, SIGUSR1);
sleep(1);
printf("\tP: about to terminate\n");
exit(0);
}
====
Scenario B
$ ./seccomp_unotify_restart_scen_B
C: installed seccomp: fd 3
C: woke 1 waiters
C: About to call pause()
P: child installed seccomp fd 3
P: about to SECCOMP_IOCTL_NOTIF_RECV
P: got notif: id=17773741941218455591 pid=25052 nr=34
P: about to send SIGUSR1 to child...
P: about to SECCOMP_IOCTL_NOTIF_RECV
C: sigusr1_handler handler invoked
P: got notif: id=17773741941218455592 pid=25052 nr=34
P: about to send SIGUSR1 to child...
P: about to SECCOMP_IOCTL_NOTIF_RECV
C: sigusr1_handler handler invoked
P: got notif: id=17773741941218455593 pid=25052 nr=34
P: about to send SIGUSR1 to child...
P: about to SECCOMP_IOCTL_NOTIF_RECV
C: sigusr1_handler handler invoked
P: got notif: id=17773741941218455594 pid=25052 nr=34
P: about to send SIGUSR1 to child...
C: sigusr1_handler handler invoked
C: got pdeath signal on parent termination
C: about to terminate
/* Modified version of code from Jann Horn */
#define _GNU_SOURCE
#include <stdio.h>
#include <signal.h>
#include <err.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sched.h>
#include <stddef.h>
#include <string.h>
#include <limits.h>
#include <inttypes.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <linux/seccomp.h>
#include <linux/filter.h>
#include <linux/futex.h>
struct {
int seccomp_fd;
} *shared;
static void
sigusr1_handler(int sig, siginfo_t * info, void *uctx)
{
printf("C: sigusr1_handler handler invoked\n");
}
static void
sigusr2_handler(int sig, siginfo_t * info, void *uctx)
{
printf("C: got pdeath signal on parent termination\n");
printf("C: about to terminate\n");
exit(0);
}
static size_t
max_size(size_t a, size_t b)
{
return (a > b) ? a : b;
}
int
main(void)
{
setbuf(stdout, NULL);
/* Allocate memory that will be shared by parent and child */
shared = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_SHARED, -1, 0);
if (shared == MAP_FAILED)
err(1, "mmap");
shared->seccomp_fd = -1;
/* glibc's clone() wrapper doesn't support fork()-style usage */
/* Child process and parent share file descriptor table */
pid_t child = syscall(__NR_clone, CLONE_FILES | SIGCHLD,
NULL, NULL, NULL, 0);
if (child == -1)
err(1, "clone");
/* CHILD */
if (child == 0) {
/* don't outlive the parent */
prctl(PR_SET_PDEATHSIG, SIGUSR2);
if (getppid() == 1)
exit(0);
/* Install seccomp filter */
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
struct sock_filter insns[] = {
BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
offsetof(struct seccomp_data, nr)),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_pause, 0, 1),
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
};
struct sock_fprog prog = {
.len = sizeof(insns) / sizeof(insns[0]),
.filter = insns
};
int seccomp_ret = syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER,
SECCOMP_FILTER_FLAG_NEW_LISTENER, &prog);
if (seccomp_ret < 0)
err(1, "install");
printf("C: installed seccomp: fd %d\n", seccomp_ret);
/* Place the notifier FD number into the shared memory */
__atomic_store(&shared->seccomp_fd, &seccomp_ret,
__ATOMIC_RELEASE);
/* Wake the parent */
int futex_ret =
syscall(__NR_futex, &shared->seccomp_fd, FUTEX_WAKE,
INT_MAX, NULL, NULL, 0);
printf("C: woke %d waiters\n", futex_ret);
/* Establish SA_RESTART handler for SIGUSR1 */
struct sigaction act = {
.sa_sigaction = sigusr1_handler,
.sa_flags = SA_RESTART | SA_SIGINFO
};
if (sigaction(SIGUSR1, &act, NULL))
err(1, "sigaction");
struct sigaction act2 = {
.sa_sigaction = sigusr2_handler,
.sa_flags = 0
};
if (sigaction(SIGUSR2, &act2, NULL))
err(1, "sigaction");
/* Make a blocking system call */
printf("C: About to call pause()\n");
pause();
perror("C: pause returned");
exit(0);
}
/* PARENT */
/* Wait for futex wake-up from child */
int futex_ret = syscall(__NR_futex, &shared->seccomp_fd, FUTEX_WAIT,
-1, NULL, NULL, 0);
if (futex_ret == -1 && errno != EAGAIN)
err(1, "futex wait");
/* Get notification FD from the child */
int fd = __atomic_load_n(&shared->seccomp_fd, __ATOMIC_ACQUIRE);
printf("\tP: child installed seccomp fd %d\n", fd);
/* Discover seccomp buffer sizes and allocate notification buffer */
struct seccomp_notif_sizes sizes;
if (syscall(__NR_seccomp, SECCOMP_GET_NOTIF_SIZES, 0, &sizes))
err(1, "notif_sizes");
struct seccomp_notif *notif =
malloc(max_size(sizeof(struct seccomp_notif),
sizes.seccomp_notif));
if (!notif)
err(1, "malloc");
for (int i = 0; i < 4; i++) {
printf("\tP: about to SECCOMP_IOCTL_NOTIF_RECV\n");
memset(notif, '\0', sizes.seccomp_notif);
if (ioctl(fd, SECCOMP_IOCTL_NOTIF_RECV, notif))
err(1, "notif_recv");
printf("\tP: got notif: id=%llu pid=%u nr=%d\n",
notif->id, notif->pid, notif->data.nr);
sleep(1);
printf("\tP: about to send SIGUSR1 to child...\n");
kill(child, SIGUSR1);
}
sleep(1);
exit(0);
}
====
Reported-by: Jann Horn <jannh@google.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
In the usual case, read(fd, buf, PATH_MAX) will return PATH_MAX
bytes that include trailing garbage after the pathname. So the
right check is to scan from the start of the buffer to see if
there's a NUL, and error if there is not.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
After some discussions with Jann Horn, perhaps a better way of
dealing with an invalid target pathname is to trigger an
error for the system call.
Reported-by: Jann Horn <jannh@google.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
From a conversation with Jann Horn:
[[
>>>> struct seccomp_notif_resp *resp = malloc(sizes.seccomp_notif_resp);
>>>
>>> This should probably do something like max(sizes.seccomp_notif_resp,
>>> sizeof(struct seccomp_notif_resp)) in case the program was built
>>> against new UAPI headers that make struct seccomp_notif_resp big, but
>>> is running under an old kernel where that struct is still smaller?
>>
>> I'm confused. Why? I mean, if the running kernel says that it expects
>> a buffer of a certain size, and we allocate a buffer of that size,
>> what's the problem?
>
> Because in userspace, we cast the result of malloc() to a "struct
> seccomp_notif_resp *". If the kernel tells us that it expects a size
> smaller than sizeof(struct seccomp_notif_resp), then we end up with a
> pointer to a struct that consists partly of allocated memory, partly
> of out-of-bounds memory, which is generally a bad idea - I'm not sure
> whether the C standard permits that. And if userspace then e.g.
> decides to access some member of that struct that is beyond what the
> kernel thinks is the struct size, we get actual OOB memory accesses.
Got it. (But gosh, this seems like a fragile API mess.)
I added the following to the code:
/* When allocating the response buffer, we must allow for the fact
that the user-space binary may have been built with user-space
headers where 'struct seccomp_notif_resp' is bigger than the
response buffer expected by the (older) kernel. Therefore, we
allocate a buffer that is the maximum of the two sizes. This
ensures that if the supervisor places bytes into the response
structure that are past the response size that the kernel expects,
then the supervisor is not touching an invalid memory location. */
size_t resp_size = sizes.seccomp_notif_resp;
if (sizeof(struct seccomp_notif_resp) > resp_size)
resp_size = sizeof(struct seccomp_notif_resp);
struct seccomp_notif_resp *resp = malloc(resp_size);
]]
Reported-by: Jann Horn <jannh@google.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
From a conversation with Jann Horn:
>> We should probably make sure here that the value we read is actually
>> NUL-terminated?
>
> So, I was curious about that point also. But, (why) are we not
> guaranteed that it will be NUL-terminated?
Because it's random memory filled by another process, which we don't
necessarily trust. While seccomp notifiers aren't usable for applying
*extra* security restrictions, the supervisor will still often be more
privileged than the supervised process.
Reported-by: Jann Horn <jannh@google.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Change "read(2) will return 0" to "read(2) may return 0".
Quoting Jann Horn:
Maybe make that "may return 0" instead of "will return 0" -
reading from /proc/$pid/mem can only return 0 in the
following cases AFAICS:
1. task->mm was already gone at open() time
2. mm->mm_users has dropped to zero (the mm only has lazytlb
users; page tables and VMAs are being blown away or have
been blown away)
3. the syscall was called with length 0
When a process has gone away, normally mm->mm_users will
drop to zero, but someone else could theoretically still be
holding a reference to the mm (e.g. someone else in the
middle of accessing /proc/$pid/mem). (Such references
should normally not be very long-lived though.)
Additionally, in the unlikely case that the OOM killer just
chomped through the page tables of the target process, I
think the read will return -EIO (same error as if the
address was simply unmapped) if the address is within a
non-shared mapping. (Maybe that's something procfs could do
better...)
Reported-by: Jann Horn <jannh@google.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Add some strongly worded text warning the reader about the correct
uses of seccomp user-space notification.
Reported-by: Jann Horn <jannh@google.com>
Cowritten-by: Christian Brauner <christian@brauner.io>
Cowritten-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The APIs used by this mechanism comprise not only seccomp(2), but
also a number of ioctl(2) operations. And any useful example
demonstrating these APIs is will necessarily be rather long.
Trying to cram all of this into the seccomp(2) page would make
that page unmanageably long. Therefore, let's document this
mechanism in a separate page.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The existing text says the structures (plural!) contain a 'struct
seccomp_data'. But this is only true for the received notification
structure (seccomp_notif). So, reword the sentence to be more
general, noting simply that the structures may evolve over time.
Add some comments to the structure definition.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Rework the description a little, and note that the close-on-exec
flag is set for the returned file descriptor.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
I can't see a reason to include it. <fcntl.h> provides O_*
constants for 'flags', S_* constants for 'mode', and mode_t.
Probably a long time ago, some of those weren't defined in
<fcntl.h>, and both headers needed to be included, or maybe it's
a historical error.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
My previous patch intended to drop the docs for the lockdown lift
SysRq, but it missed this other section that refers to lifting it
via a keyboard - an allusion to that same SysRq.
Signed-off-by: dann frazier <dann.frazier@canonical.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The patch that implemented lockdown lifting via SysRq ended up
getting dropped[*] before the feature was merged upstream. Having
the feature documented but unsupported has caused some confusion
for our users.
[*] http://archive.lwn.net:8080/linux-kernel/CACdnJuuxAM06TcnczOA6NwxhnmQUeqqm3Ma8btukZpuCS+dOqg@mail.gmail.com/
Signed-off-by: dann frazier <dann.frazier@canonical.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: David Howells <dhowells@redhat.com>
Cc: Pedro Principeza <pedro.principeza@canonical.com>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Kyle McMartin <kyle@redhat.com>
Cc: Matthew Garrett <mjg59@google.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Instead of having a monolithic 'make install', break it into
multiple targets such as 'make install-man3'. This simplifies
packaging, for example in Debian, where they break this project
into several packages: 'manpages' and 'manpages-dev', each
containing different mandirs.
The above allows for multithread installation: 'make -j'
Also, don't overwrite files that don't need to be overwritten, by
having a target for files, which makes use of make's timestamp
comparison.
This allows for much faster installation times.
For comparison, on my laptop (i7-8850H; 6C/12T):
Old Makefile:
~/src/linux/man-pages$ time sudo make >/dev/null
real 0m7.509s
user 0m5.269s
sys 0m2.614s
The times with the old makefile, varied a lot, between
5 and 10 seconds. The times after applying this patch
are much more consistent. BTW, I compared these times to
the very old Makefile of man-pages-5-09, and those were
around 3.5 s, so it was a bit of my fault to have such a
slow Makefile, when I changed the Makefile some weeks ago.
New Makefile (full clean install):
~/src/linux/man-pages$ time sudo make >/dev/null
real 0m5.160s
user 0m4.326s
sys 0m1.137s
~/src/linux/man-pages$ time sudo make -j2 >/dev/null
real 0m1.602s
user 0m2.529s
sys 0m0.289s
~/src/linux/man-pages$ time sudo make -j >/dev/null
real 0m1.398s
user 0m2.502s
sys 0m0.281s
Here we can see that 'make -j' drops times drastically,
compared to the old monolithic Makefile. Not only that,
but since when we are working with the man pages there
aren't many pages involved, times will be even better.
Here are some times with a single page changed (touched):
New Makefile (one page touched):
~/src/linux/man-pages$ touch man2/membarrier.2
~/src/linux/man-pages$ time sudo make install
- INSTALL /usr/local/share/man/man2/membarrier.2
real 0m0.988s
user 0m0.966s
sys 0m0.025s
~/src/linux/man-pages$ touch man2/membarrier.2
~/src/linux/man-pages$ time sudo make install -j
- INSTALL /usr/local/share/man/man2/membarrier.2
real 0m0.989s
user 0m0.943s
sys 0m0.049s
Also, modify the output of the make install and uninstall commands
so that a line is output for each file or directory that is
installed, similarly to the kernel's Makefile. This doesn't apply
to html targets, which haven't been changed in this commit.
Also, make sure that for each invocation of $(INSTALL_DIR), no
parents are created, (i.e., avoid `mkdir -p` behavior). The GNU
make manual states that it can create race conditions. Instead,
declare as a prerequisite for each directory its parent directory,
and let make resolve the order of creation.
Also, use ':=' instead of '=' to improve performance, by
evaluating each assignment only once.
Ensure than the shell is not called when not needed, by removing
all ";" and quotes in the commands.
See also: <https://stackoverflow.com/q/67862417/6872717>
Specify conventions and rationales used in the Makefile in a comment.
Add copyright.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Document also why each header is required
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This function doesn't use any flags or special types, so there's
no reason to include <asm/unistd.h>; remove it. Add the includes
needed for syscall(2) only.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Also document why each header is needed.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This error can occur if the caller is does not have CAP_IPC_LOCK
and is not a member of the sysctl_hugetlb_shm_group.
Reported-by: Yang Xu <xuyang2018.jy@fujitsu.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
As a deprecated feature, it appears that the RLIMIT_MEMLOCK
can also be used to permit huge page allocation, but let's
not document that for now.
In the Linux 5.12, see fs/hugetlbfs/inode.c.
static int can_do_hugetlb_shm(void)
{
kgid_t shm_group;
shm_group = make_kgid(&init_user_ns, sysctl_hugetlb_shm_group);
return capable(CAP_IPC_LOCK) || in_group_p(shm_group);
}
...
struct file *hugetlb_file_setup(const char *name, size_t size,
vm_flags_t acctflag, struct user_struct **user,
int creat_flags, int page_size_log)
{
...
if (creat_flags == HUGETLB_SHMFS_INODE && !can_do_hugetlb_shm()) {
*user = current_user();
if (user_shm_lock(size, *user)) {
task_lock(current);
pr_warn_once("%s (%d): Using mlock ulimits for SHM_HUGETLB is deprecated\n",
current->comm, current->pid);
task_unlock(current);
} else {
*user = NULL;
return ERR_PTR(-EPERM);
}
}
...
}
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The installation path was changed recently (See 'prefix' in the
Makefile). I forgot to update the README with those changes.
Fix it.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Explain also why headers are needed.
And some ffix.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
It is only used for providing 'sigset_t'. We're only documenting
(with some exceptions) the includes needed for constants and the
prototype itself. And 'sigset_t' is better documented in
system_data_types(7). Remove that include.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
All of the constants used by mknod() are defined in <sys/stat.h>.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
AFAICS, there's no use for <unistd.h> here. The prototype is
declared in <sys/mman.h>, and there are no constants needed.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Remove the libkeyutils prototype from the synopsis, which isn't
documented in the rest of the page, and as NOTES says, it's
probably better to use the various library functions.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The constants needed for using this function are defined in
<linux/ipc.h>. Add the include, even when those constants are not
mentioned in this manual page.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Of course that is for the glibc wrapper. As all of the other
pages that don't explicitly say otherwise.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
In this case there's a wrapper provided by libaio,
but this page documents the raw syscall.
Also remove <linux/time.h> from the includes: 'struct timespec'
is already documented in system_data_types(7), where the
information is more up to date.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
In this case there's a wrapper provided by libaio,
but this page documents the raw syscall.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
At the same time, document only headers that are required
for calling the function, or those that are specific to the
function:
<unistd.h> is required for the syscall() prototype.
<sys/syscall.h> is required for the syscall name SYS_xxx.
<linux/futex.h> is specific to this syscall.
However, uint32_t is generic enough that it shouldn't be
documented here. The system_data_types(7) page already documents
it, and is more precise about it. The same goes for timespec.
As a general rule a man[23] page should document the header that
includes the prototype, and all of the headers that define macros
that should be used with the call. However, the information about
types should be restricted to system_data_types(7) (and that page
should probably be improved by adding types), except for types
that are very specific to the call. Otherwise, we're duplicating
info and it's then harder to maintain, and probably outdated in
the future.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This complements commit e3eba861bd.
Since we don't need syscall(2) anymore, we don't need SYS_* definitions.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
On 5/10/21 7:13 PM, Alejandro Colomar (man-pages) wrote:
> Hi Michael,
>
> On 5/10/21 1:39 AM, Michael Kerrisk (man-pages) wrote:
>>> - Specify shebang
>>
>> Why? It's not quite obvious to me, and the commit message
>> should really explain...
>
> Hmmm. I have some minor reasons to add it, but not a really good one.
>
> * Some editors don't recognize 'Makefile' as a special name, so the
> shebang helps detecting which language the file is using (e.g., for
> coloring).
>
> * I tend to subdivide a big Makefile into a small Makefile and many
> submakefiles stored in <./libexec/>. Those obviously need different
> names, and given that the makefile extension is not very standard (I use
> .mk), having a shebang helps knowing what the file is. After that, I
> also have it on the main Makefile for consistency. But here we only
> have one Makefile, so it doesn apply very much.
I think I'll remove it. It is kind of idiosyncratic, leaves the
reader asking "why?".
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Ignore everything new by default.
This avoids having to update the .gitignore when we need to ignore
something new. It also avoids accidents that may add an unwanted
temporary file.
Cc: Debian man-pages <manpages@packages.debian.org>
Cc: Dr. Tobias Quathamer <toddy@debian.org>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
fpurge(i_stream) does the same as fflush(i_stream), AFAIK.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
AT_EMPTY_PATH works with empty strings (""), but not with NULL
(or at least it's not obvious).
The relevant kernel code is the following:
linux$ sed -n 189,198p fs/namei.c
result->refcnt = 1;
/* The empty path is special. */
if (unlikely(!len)) {
if (empty)
*empty = 1;
if (!(flags & LOOKUP_EMPTY)) {
putname(result);
return ERR_PTR(-ENOENT);
}
}
Reported-by: Walter Harms <wharms@bfs.de>
Cc: Theodore Ts'o <tytso@mit.edu>
Cc: Adam Borowski <kilobyte@angband.pl>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
See <bits/byteswap.h> in glibc.
These macros call functions of the form __bswap_N(),
which use uintN_t.
Even though it's true that they are macros,
it's transparent to the user.
The user will see their results casted to unsigned types
after the conversion due to the underlying functions,
so it's better to document these as the underlying functions,
specifying the types.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Both POSIX and glibc use 'restrict' in
pthread_attr_getinheritsched().
Let's use it here too.
.../glibc$ grep_glibc_prototype pthread_attr_getinheritsched
sysdeps/htl/pthread.h:90:
extern int pthread_attr_getinheritsched (const pthread_attr_t *__restrict __attr,
int *__restrict __inheritsched)
__THROW __nonnull ((1, 2));
sysdeps/nptl/pthread.h:313:
extern int pthread_attr_getinheritsched (const pthread_attr_t *__restrict
__attr, int *__restrict __inherit)
__THROW __nonnull ((1, 2));
.../glibc$
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
'C library/kernel differences' was added to BUGS incorrectly.
Fix it
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Those pages didn't exist. Fix the section number.
I noticed the typo thanks to the HTML pages on man7.org.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Prerequisites can run in parallel. This wouldn't make any sense
when uninstalling and installing again.
For that, use consecutive commands, which run one after the other
even with multiple cores.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
IMPORTANT for distributions:
This changes prefix to be '/usr/local' as is expected by default,
instead of the old '/usr' value.
- Use standard variables:
- prefix should be '/usr/local'
- mandir (instead of MANDIR)
- htmldir (instead of HTDIR)
- ...
see <https://www.gnu.org/software/make/manual/html_node/Directory-Variables.html>
- Use standard targets:
- html (build html files; don't install them)
- install-html (instead of html)
- installdirs (instead of 'mkdir -p'/'install -d' inside other targets)
- ...
see <https://www.gnu.org/software/make/manual/html_node/Standard-Targets.html#Standard-Targets>
- Use .PHONY
- ?= is not needed. User input overrides any assignment. Use =
- Use standard command variables, instead of directly calling commands.
- $(INSTALL_DATA) (instead of install -m 644)
- $(INSTALL_DIR) (instead of install -d -m 755 or mkdir -p)
see <https://www.gnu.org/software/make/manual/html_node/Command-Variables.html#Command-Variables>
- Specify SHELL = /bin/bash
- Specify shebang
- Allow variable html extension (or no extension at all)
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
mkdir -p doesn't fail if the directory already exists.
Remove redundant checks.
Use .html as default HTDIR.
Remove checks for undefined HTDIR.
Show what the target does, as with other targets (remove '@').
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
I clarified the code about two things:
- Checking how many arguments are being passed.
Here, some functions didn't reject extra arguments when they
weren't being used. Fix that.
I also changed the code to use $#, which is more explicit.
And use arithmetic expressions, which better indicate that
we're dealing with numbers.
- Remove unneeded options from sort.
Reported-by: Stefan Puiu <stefan.puiu@gmail.com>
After Stefan asked about why am I using 'sort -V',
I noticed that I really don't need '-V', and it may confuse
people trying to understand the script, so even though I
slightly prefer the output of 'sort -V', in this case, it's
better to use the simpler 'sort' (yet I need 'sort', to
maintain consistency in the results (find is quite random)).
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Fix the error messages to clearly show that both dirs and manual
pages are accepted, and that more than one argument is accepted.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This patch makes man_lsfunc() search for the function prototypes,
instead of relying on the current manual page formatting,
which might change in the future, and break this function.
It also simplifies the code, by reusing man_section().
Create a new function sed_rm_ccomments(), which is needed by
man_lsfunc(), and may also be useful in other cases.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The output of 'git status' is not stable.
The more stable 'git status --porcelain' is more complex,
and scripting around it would be more complex.
However, 'git diff --staged --name-only' produces
the output that we were lookiong for.
Reported-by: Jakub Wilk <jwilk@jwilk.net>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Neither POSIX or glibc use 'const' in
pthread_mutexattr_setrobust().
Remove it.
.../glibc$ grep_glibc_prototype pthread_mutexattr_setrobust
sysdeps/htl/pthread.h:355:
extern int pthread_mutexattr_setrobust (pthread_mutexattr_t *__attr,
int __robustness)
__THROW __nonnull ((1));
sysdeps/nptl/pthread.h:888:
extern int pthread_mutexattr_setrobust (pthread_mutexattr_t *__attr,
int __robustness)
__THROW __nonnull ((1));
.../glibc$
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The rest of the page writes the characters without naming them.
Follow that convention.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Improved the `getopt(3)` man page in the following ways:
1) Defined the existing term "legitimate option character".
2) Added an additional NOTE stressing that arguments are parsed in strict
order and the implications of this when numeric options are utilised.
Signed-off-by: James O. D. Hunt <jamesodhunt@gmail.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Despite my mention of this spawning a hilarious discussion
on IRC, this alignment restriction should be 128-bit, not
126-bit.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Add a missing "to" in an "in order to" formulation.
Signed-off-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
CIFS flock() locks behave differently than the standard. Give overview
of those differences.
Here is the rendered text:
CIFS details
In Linux kernels up to 5.4, flock() is not propagated over SMB. A file
with such locks will not appear locked for remote clients.
Since Linux 5.5, flock() locks are emulated with SMB byte-range locks
on the entire file. Similarly to NFS, this means that fcntl(2) and
flock() locks interact with one another. Another important side-effect
is that the locks are not advisory anymore: any IO on a locked file
will always fail with EACCES when done from a separate file descriptor.
This difference originates from the design of locks in the SMB proto-
col, which provides mandatory locking semantics.
Remote and mandatory locking semantics may vary with SMB protocol,
mount options and server type. See mount.cifs(8) for additional infor-
mation.
Signed-off-by: Aurelien Aptel <aaptel@suse.com>
Discussion: linux-man <https://lore.kernel.org/linux-man/20210302154831.17000-1-aaptel@suse.com/>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
In b0b19983d9 we removed
<sys/types.h>. For the same reasons there, remove now <sys/ipc.h>
from many pages.
If someone wonders why <sys/ipc.h> was needed, the reason was to
get all the definitions of IPC_* constants. However, that header
is now included by <sys/msg.h>, so it's not needed anymore to
explicitly include it. Quoting POSIX: "In addition, the
<sys/msg.h> header shall include the <sys/ipc.h> header."
There were some remaining cases where I forgot to remove
<sys/types.h>; remove them now too.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
AFAICS, all types and constants used by these functions are
defined in <fcntl.h>.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
A few architectures have a different call signature for pipe().
Since those architectures are the minority, place the prototype
at the end of the SYNOPSIS, rather than the start.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
SEE ALSO: move pam_namespace(8) from namespaces(7) to
mount_namespaces(7) (since pam_namespace(8) makes use of
mount namespaces specifically).
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Userfaultfd write-protect mode is supported starting from Linux 5.7.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
[alx: ffix + srcfix]
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
UFFD_FEATURE_THREAD_ID is supported in Linux 4.14.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Write-protect mode is supported starting from Linux 5.7.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
UFFD_FEATURE_THREAD_ID is supported since Linux 4.14.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
[alx: srcfix]
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
My initial reading of this was that type modifiers were probably
not supported. But they are, and this is actually documented
further up, in the type modifiers documentation. But to make it
clearer, let's copy the language that printf(3) has in its %n
section.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
In this case there's a wrapper provided by libaio,
but this page documents the raw kernel syscall.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
<linux/unistd.h> is not needed. We need <unistd.h> for syscall(),
and <sys/syscall.h> for SYS_exit_group.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Add <linux/fcntl.h>, which contains AT_* definitions used by
execveat().
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The CLONE_* constants seem to be available from either
<linux/sched.h> or <sched.h>, and since clone3() already
includes <linux/sched.h> for 'struct clone_args', <sched.h>
is not really needed, AFAICS; however, to avoid confusion,
I also included <sched.h> for clone3() for consistency:
clone() is getting CLONE_* from <sched.h>, and it would confuse
the reader if clone3() got the same CLONE_* constants from a
different header.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
AFAICS, there's no reason to include that.
All of the macros that this function uses
are already defined in the other headers.
Cc: glibc <libc-alpha@sourceware.org>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The page didn't specify includes, and the syscalls are extinct, so
instead of adding incomplete information about includes, just
leave it without any includes.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Only the include that provides the prototype doesn't need a comment.
Also sort the includes alphabetically.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Only the one that provides the prototype doesn't need a comment.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
<linux/fs.h> doesn't seem to be needed!
Only the include that provides the prototype doesn't need a comment.
Also sort the includes alphabetically.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Only the include that provides the prototype doesn't need a comment.
Also sort the includes alphabetically.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Only the one that provides the prototype doesn't need a comment.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
[mtk: Alex's change switches the comment to the more generally used
form "Definition of..."]
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
<sys/time.h> is not needed to get the function declaration nor any
constant used by the function. It was only needed (before
POSIX.1) to get 'struct timeval', but that information would be
more suited for system_data_types(7), and not for this page.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
<sys/time.h> is not required by any of the function declarations
or macro definitions used by these functions. It may be (or maybe
not) needed by some type inside the rlimit structure, but that
info belongs in system_data_types(7), not here.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
<sys/types.h> was only needed for size_t, AFAIK. That is already
(and more precisely) documented in system_data_types(7). Let's
remove it here, as it's not really needed for calling add_key().
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
I couldn't find a reason for including <unistd.h>. All the macros
used by fcntl() are defined in <fcntl.h>. For comparison, FreeBSD
and OpenBSD don't specify <unistd.h> in their manual pages.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This function never returns to its caller.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
ENODATA is an XSI STREAMS extension (not base POSIX).
Linux reused the name for extended attributes.
The current manual pages don't use ENODATA with its POSIX
meaning, so use the xattr(7) specific text, and leave the POSIX
meaning for a secondary paragraph.
Reported-by: Mark Kettenis <kettenis@openbsd.org>
Reported-by: Florian Weimer <fw@deneb.enyo.de>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Checked via the latest glibc source. execvpe calls getenv("PATH") and
searches that; the PATH in envp does not affect the search.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
In Linux kernel 5.12, a new mode flag, MPOL_F_NUMA_BALANCING, is
added to set_mempolicy() to optimize the page placement among the
NUMA nodes with the NUMA balancing mechanism even if the memory of
the applications is bound with MPOL_BIND. This patch updates the
man page for the new mode flag.
Related kernel commits:
bda420b985054a3badafef23807c4b4fa38a3dff
[mtk: Minor fixes to commit message]
Signed-off-by: "Huang, Ying" <ying.huang@intel.com>
Cc: "Michael Kerrisk" <mtk.manpages@gmail.com>
[ alx: srcfix ]
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The envp argument specifies the environment of the new process image,
not "the environment of the caller".
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
The format string refers to the whole string passed in 'format'.
The syntax referred to is that of a conversion specification,
as called in the manual page.
Use specific language.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Can we add a small syntax structure for format string in printf(3)
manual. I personally find if easier to remember and scan. This has
been taken from OpenBSD printf(3) manual.
Signed-off-by: Utkarsh Singh <utkarsh190601@gmail.com>
[ alx: ffix ]
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Add a sentence explaining what dup2() does in terms of file
descriptors and open file descriptions.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Sometimes people are confused, thinking a file descriptor is just a
number. To help avoid such confusions, add text highlighting that
a file descriptor is an index to an entry in the process's FD table.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
As can be seen by any number of StackOverflow questions, people
persistently misunderstand what dup() does, and the existing manual
page text, which talks of "copying" a file descriptor doesn't help.
Rewrite the text a little to try to prevent some of these
misunderstandings, in particular noting at the start that dup()
allocates a new file descriptor.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>