NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/58425: negation of pid or pgid is UB for INT_MIN
The following reply was made to PR kern/58425; it has been noted by GNATS.
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: kre%NetBSD.org@localhost, gnats-admin%NetBSD.org@localhost, netbsd-bugs%NetBSD.org@localhost
Subject: Re: kern/58425: negation of pid or pgid is UB for INT_MIN
Date: Sun, 14 Jul 2024 13:55:11 +0000
> Date: Sun, 14 Jul 2024 10:52:19 +0700
> From: Robert Elz <kre%munnari.OZ.AU@localhost>
>
> Date: Sat, 13 Jul 2024 19:55:00 +0000 (UTC)
> From: campbell+netbsd%mumble.net@localhost
> Message-ID: <20240713195500.A81291A923C%mollari.NetBSD.org@localhost>
>
> | This could be a theoretical issue or it could be a practical issue,
>
> I believe that unless we have some architecture which traps when
> executing -INT_MIN rather than just generating INT_MIN as the result
> (which is conceivable, but I doubt anything supported will do that)
> then I suspect this is really a non-issue for practical purposes.
> Even if the architecture were to generate a random value (which UB
> allows) it would not be truly harmful ... an application is allowed
> to send any random value to these sys calls, and things must work,
> that the random value was generated by this operation, rather than
> some other way really doesn't matter.
The issue isn't so much that the architecture's SUB or NEG instruction
might trap or produce wild behaviour -- although in principle it
could, and not even in a pathological architecture design, just like
signed division INT_MIN/-1 traps on x86.
The more likely risk is that a _compiler_ may draw an inference from
an unprotected -pgid expression -- it may infer that along any control
flow paths that unconditionally pass through that expression, pgid
must not be INT_MIN, because if it were then the behaviour would be
undefined and we all know C programmers never write programs that
could lead to UB on the possible inputs.
So, for example, a compiler might optimize (a)
*p = -pgid;
return (pgid == INT_MIN);
into
*p = -pgid;
return false;
or it might optimize (b)
return (-pgid == pgid);
into
return (pgid == 0);
where you might expect it (or require it, with -fwrapv) to be
equivalent instead to
return (pgid == 0 || pgid == INT_MIN);
I haven't seen (a) in practice but (b) is easy to exhibit:
https://godbolt.org/z/rzxjf38aY
> I am however in the process of validating the value, and not performing
> the undefined operation. Note, that as (ktrace excepted, where the
> pid arg is actually defined to be an int) generally dealing with pid_t
> values, which we cannot assume are int ... it could be short (and once
> was, even earlier I think it might have been char, not that the name
> "pid_t" existed then, but that was a long long time ago) which would
> never give a problem, it gets promoted to int for both the -pid
> operation (and so could never be INT_MIN) and to pass as a parameter.
> Alternatively, pid_t might be wider than an int (could be long)
> in which case the value might be < INT_MIN, so I am making (most of)
> the tests check that the value is > INT_MIN not just != INT_MIN.
Thanks! Maybe we should use -PID_MAX as the limit instead of INT_MIN,
to make it more resilient to (unlikely but possible) changes of the
type and easier to audit?
...Except PID_MAX apparently isn't actually the max, once we cross
~16k processes. So maybe we should have a different name for the
_real_ maximum pid.
> ps: Taylor, if you feel we need ATF test cases for this, by all means,
> go ahead.
I added one for kill(INT_MIN, 0). We should add more tests for ktrace
and for FIOSETOWN on a tty (uses tty.c path) and a pipe or socket
(uses kern_proc.c fsetown path).
Home |
Main Index |
Thread Index |
Old Index