Collin Funk <[email protected]> writes: > That test program assumes that nice() does not clamp the niceness to the > supported range as it is supposed to [1]. This is the case on GNU/Hurd, > so I will submit a bug report for that later. > > The output is the same on a normal and privileged user: > > $ gcc main.c ./a.out > starting nice: 0 > minimum nice: 0 > maximum nice: 38 > minimum errno: EPERM > maximum errno: ESRCH > > This patch clamps it to the supported range and adds some tests. Here is > the corrected behavior: > > $ ./src/nice -n +100 ./src/nice > 38
Actually my original patch did not work if 'nice' was invoked with a niceness greater than zero. This v2 patch fixes that and adds more tests. Collin
>From 40a9af197767c1a2b4bb2cc4a87f15dad581efa5 Mon Sep 17 00:00:00 2001 Message-ID: <40a9af197767c1a2b4bb2cc4a87f15dad581efa5.1762672551.git.collin.fu...@gmail.com> From: Collin Funk <[email protected]> Date: Sat, 8 Nov 2025 20:30:08 -0800 Subject: [PATCH v2] nice: clamp the niceness correctly on GNU/Hurd * NEWS: Mention the bug fix. * src/nice.c (MIN_ADJUSTMENT): Set to 0 on the Hurd. (MAX_ADJUSTMENT): Set to 38 on the Hurd. (main): Clamp the niceness to be greater or equal to MIN_ADJUSTMENT and less than or equal to MAX_ADJUSTMENT. * tests/nice/nice.sh: Add some tests for the Hurd's ranges. --- NEWS | 4 ++++ src/nice.c | 30 ++++++++++++++++++++++++++++++ tests/nice/nice.sh | 46 ++++++++++++++++++++++++++++++++++++---------- 3 files changed, 70 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index 7e7dc6376..46df91b62 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,10 @@ GNU coreutils NEWS -*- outline -*- will no longer always set a __CF_USER_TEXT_ENCODING environment variable. [bug introduced in coreutils-9.8] + 'nice' now limits the adjusted niceness value to its supported range on + GNU/Hurd. + [This bug was present in "the beginning".] + 'numfmt' no longer reads out-of-bounds memory with trailing blanks in input. [bug introduced with numfmt in coreutils-8.21] diff --git a/src/nice.c b/src/nice.c index 1c3f2a038..803e0c017 100644 --- a/src/nice.c +++ b/src/nice.c @@ -167,12 +167,42 @@ main (int argc, char **argv) /* If the requested adjustment is outside the valid range, silently bring it to just within range; this mimics what "setpriority" and "nice" do. */ +#ifdef __gnu_hurd__ + /* GNU/Hurd's range is 0 to 38. */ + enum { MIN_ADJUSTMENT = 0, MAX_ADJUSTMENT = 38 }; +#else enum { MIN_ADJUSTMENT = 1 - 2 * NZERO, MAX_ADJUSTMENT = 2 * NZERO - 1 }; +#endif long int tmp; if (LONGINT_OVERFLOW < xstrtol (adjustment_given, nullptr, 10, &tmp, "")) error (EXIT_CANCELED, 0, _("invalid adjustment %s"), quote (adjustment_given)); +#ifdef __gnu_hurd__ + /* GNU/Hurd's nice(2) does not clamp the given value to the supported + range. See <https://sourceware.org/PR33614>. */ + errno = 0; + current_niceness = GET_NICENESS (); + if (current_niceness == -1 && errno != 0) + error (EXIT_CANCELED, errno, _("cannot get niceness")); + if (tmp < 0) + { + int sum; + if (ckd_add (&sum, current_niceness, tmp) || sum < MIN_ADJUSTMENT) + adjustment = MIN_ADJUSTMENT - current_niceness; + else + adjustment = tmp; + } + else + { + int sum; + if (ckd_add (&sum, current_niceness, tmp) || MAX_ADJUSTMENT < sum) + adjustment = MAX_ADJUSTMENT - current_niceness; + else + adjustment = tmp; + } +#else adjustment = MAX (MIN_ADJUSTMENT, MIN (tmp, MAX_ADJUSTMENT)); +#endif } if (i == argc) diff --git a/tests/nice/nice.sh b/tests/nice/nice.sh index 7e274ca0d..2133fa519 100755 --- a/tests/nice/nice.sh +++ b/tests/nice/nice.sh @@ -71,16 +71,42 @@ done # Test negative niceness - command must be run whether or not change happens. if test x$(nice -n -1 nice 2> /dev/null) = x0 ; then - # unprivileged user - warn about failure to change - nice -n -1 true 2> err || fail=1 - compare /dev/null err && fail=1 - mv err exp || framework_failure_ - nice --1 true 2> err || fail=1 - compare exp err || fail=1 - # Failure to write advisory message is fatal. Buggy through coreutils 8.0. - if test -w /dev/full && test -c /dev/full; then - returns_ 125 nice -n -1 nice > out 2> /dev/full || fail=1 - compare /dev/null out || fail=1 + # GNU/Hurd does not allow negative niceness even if we are privileged user. + if test "$(uname)" = GNU; then + # Check that the lowest niceness is 0. + nice -n -1 nice > out || fail=1 + echo '0' > exp || framework_failure_ + compare exp out || fail=1 + # Check that the highest niceness is 38. + nice -n 39 nice > out || fail=1 + echo '38' > exp || framework_failure_ + compare exp out || fail=1 + # GNU/Hurd's nice(2) does not clamp the given value to the supported range. + # Check that we workaround the bug. See <https://sourceware.org/PR33614>. + nice -n 1 nice -n 36 nice > out|| fail=1 + echo '37' > exp || framework_failure_ + compare exp out || fail=1 + nice -n 1 nice -n 38 nice > out || fail=1 + echo '38' > exp || framework_failure_ + compare exp out || fail=1 + nice -n 2 nice -n -1 nice > out || fail=1 + echo '1' > exp || framework_failure_ + compare exp out || fail=1 + nice -n 2 nice -n -3 nice > out || fail=1 + echo '0' > exp || framework_failure_ + compare exp out || fail=1 + else + # unprivileged user - warn about failure to change + nice -n -1 true 2> err || fail=1 + compare /dev/null err && fail=1 + mv err exp || framework_failure_ + nice --1 true 2> err || fail=1 + compare exp err || fail=1 + # Failure to write advisory message is fatal. Buggy through coreutils 8.0. + if test "$(uname)" != GNU && test -w /dev/full && test -c /dev/full; then + returns_ 125 nice -n -1 nice > out 2> /dev/full || fail=1 + compare /dev/null out || fail=1 + fi fi else # superuser - change succeeds -- 2.51.1
