[CCing Jens because of the discussion below about IOPRIO_WHO_USER
below; he may have a comment]
[CCing Марк, who independently noted the lack of documentation for
IOPRIO_WHO_PROCESS, who==0 .]
[CCing Colin McCabe who sent other recent fixes for the ioprio_set.2 page]

On Sat, Dec 17, 2011 at 11:26 PM, Kalle Olavi Niemitalo <k...@iki.fi> wrote:
> Package: manpages-dev
> Version: 3.32-0.2
> Severity: wishlist
> File: /usr/share/man/man2/ioprio_get.2.gz
>
> The ioprio_get(2) manual page describes the meanings of the which
> and who parameters:
>
>> IOPRIO_WHO_PROCESS
>>        who is a process ID identifying a single process.
>>
>> IOPRIO_WHO_PGRP
>>        who is a process group ID identifying all the members of
>>        a process group.
>>
>> IOPRIO_WHO_USER
>>        who is a user ID identifying all of the processes that
>>        have a matching real UID.
>
> The manual page should mention that IOPRIO_WHO_PROCESS and
> IOPRIO_WHO_PGRP also allow who==0.

Yes.

> As implemented in
> fs/ioprio.c, who==0 means the calling process or its process
> group.  The ioprio program in util-linux already uses the
> feature.  This is worth documenting separately because
> e.g. tcsetpgrp does not treat pgrp==0 in that way.

Agreed, this should be documented since various APIs interpret pgrp==0
differently. Some (e.g., killpg(2)) are like this syscall, others are
not.

> For IOPRIO_WHO_USER, the situation is more complex: who==0 means
> the root user in ioprio_set but the current user (I think the
> real UID of the calling process) in ioprio_get.  (That
> inconsistency might even be a bug.)

So, I'm not sure I'm following the kernel code too well here...
@Jens, your comments would be very welovem.

In ioprio_get() (Linux 3.5 kernel source file fs/ioprio.c), I see the following:

                case IOPRIO_WHO_USER:
                        uid = make_kuid(current_user_ns(), who);
                        if (!who)
                                user = current_user();
                        else
                                user = find_user(uid);

                        if (!user)
                                break;

                        do_each_thread(g, p) {
                                if (!uid_eq(task_uid(p), user->uid))
                                        continue;
                                tmpio = get_task_ioprio(p);
                                if (tmpio < 0)
                                        continue;
                                if (ret == -ESRCH)
                                        ret = tmpio;
                                else
                                        ret = ioprio_best(ret, tmpio);
                        } while_each_thread(g, p);

                        if (who)
                                free_uid(user);
                        break;

In ioprio_set(), I see:

                case IOPRIO_WHO_USER:
                        uid = make_kuid(current_user_ns(), who);
                        if (!uid_valid(uid))
                                break;
                        if (!who)
                                user = current_user();
                        else
                                user = find_user(uid);

                        if (!user)
                                break;

                        do_each_thread(g, p) {
                                if (!uid_eq(task_uid(p), uid))
                                        continue;
                                ret = set_task_ioprio(p, ioprio);
                                if (ret)
                                        goto free_uid;
                        } while_each_thread(g, p);
free_uid:
                        if (who)
                                free_uid(user);
                        break;

This suggests to me that you are right Kalle, in your interpretation
of who==0 for the IOPRIO_WHO_USER, since ioprio_get() uses
current_iser()->uid for its scan while ioprio_get() uses the UID
returned by make_kuid() (So, to be precise, I think who==0 in this
case means "the UID of the uer who is thye super user in this user
namespace"). If that's correct, it does of course need to be
documented. I'd be happy to get confirmation from Jens on this point.

I suppose that the differing meaning of who==0 for IOPRIO_WHO_USER in
ioprio_get() versus ioprio_set() is by design. But if so, like you
Kalle, I agree that it's a design point that is likely to surprise
users (and surprises here might have security implications). Again,
I'd like to get input from Jens.

In the meantime, I've applied the patch below to cover the other two cases.

Thanks,

Michael

--- a/man2/ioprio_set.2
+++ b/man2/ioprio_set.2
@@ -56,10 +56,16 @@ is interpreted, and has one of the following values:
 .B IOPRIO_WHO_PROCESS
 .I who
 is a process ID or thread ID identifying a single process or thread.
+If
+.I who
+is 0, then operate on the calling thread.
 .TP
 .B IOPRIO_WHO_PGRP
 .I who
 is a process group ID identifying all the members of a process group.
+If
+.I who
+is 0, then operate on the process group of which the caller is a member.
 .TP
 .B IOPRIO_WHO_USER
 .I who

-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Author of "The Linux Programming Interface"; http://man7.org/tlpi/


--
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to