[PATCH] Cygwin: setpriority, sched_setparam: fail if Windows sets a lower priority
Christian Franke
Christian.Franke@t-online.de
Wed Nov 27 09:39:07 GMT 2024
A minor improvement of POSIX emulation.
--
Regards,
Christian
-------------- next part --------------
From 7d089e109f32fe44f331ca142e8dc8747f0e9db3 Mon Sep 17 00:00:00 2001
From: Christian Franke <christian.franke@t-online.de>
Date: Wed, 27 Nov 2024 10:26:38 +0100
Subject: [PATCH] Cygwin: setpriority, sched_setparam: fail if Windows sets a
lower priority
Windows silently sets a lower priority than requested if the new priority
requires administrator privileges. Revert to previous priority and fail
with EACCES or EPERM in this case.
Signed-off-by: Christian Franke <christian.franke@t-online.de>
---
winsup/cygwin/local_includes/miscfuncs.h | 1 +
winsup/cygwin/miscfuncs.cc | 29 ++++++++++++++++++++++++
winsup/cygwin/release/3.6.0 | 5 ++++
winsup/cygwin/sched.cc | 2 +-
winsup/cygwin/syscalls.cc | 4 ++--
5 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/winsup/cygwin/local_includes/miscfuncs.h b/winsup/cygwin/local_includes/miscfuncs.h
index d52debad1..efd7e516b 100644
--- a/winsup/cygwin/local_includes/miscfuncs.h
+++ b/winsup/cygwin/local_includes/miscfuncs.h
@@ -46,6 +46,7 @@ is_alt_numpad_event (PINPUT_RECORD pirec)
int winprio_to_nice (DWORD);
DWORD nice_to_winprio (int &);
+bool set_and_check_winprio (HANDLE proc, DWORD prio);
bool create_pipe (PHANDLE, PHANDLE, LPSECURITY_ATTRIBUTES, DWORD);
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index 4220f6275..e3bf35cf7 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -183,6 +183,35 @@ nice_to_winprio (int &nice)
return prio;
}
+/* Set Win32 priority or return false on failure. Also return
+ false and revert to the original priority if a different (lower)
+ priority is set instead. */
+bool
+set_and_check_winprio (HANDLE proc, DWORD prio)
+{
+ DWORD prev_prio = GetPriorityClass (proc);
+ if (prev_prio == prio)
+ return true;
+
+ if (!SetPriorityClass (proc, prio))
+ return false;
+
+ /* Windows silently sets a lower priority (HIGH_PRIORITY_CLASS) if
+ the new priority (REALTIME_PRIORITY_CLASS) requires administrator
+ privileges. */
+ DWORD curr_prio = GetPriorityClass (proc);
+ if (curr_prio != prio)
+ {
+ debug_printf ("Failed to set priority 0x%x, revert from 0x%x to 0x%x",
+ prio, curr_prio, prev_prio);
+ SetPriorityClass (proc, prev_prio);
+ return false;
+ }
+
+ debug_printf ("Changed priority from 0x%x to 0x%x", prev_prio, curr_prio);
+ return true;
+}
+
/* Minimal overlapped pipe I/O implementation for signal and commune stuff. */
BOOL
diff --git a/winsup/cygwin/release/3.6.0 b/winsup/cygwin/release/3.6.0
index 468a2ab24..ef7e4018f 100644
--- a/winsup/cygwin/release/3.6.0
+++ b/winsup/cygwin/release/3.6.0
@@ -43,3 +43,8 @@ What changed:
- Now using AVX/AVX2/AVX-512 instructions in signal handler does not
break their context.
+
+- nice(2), setpriority(2) and sched_setparam(2) now fail with EACCES
+ or EPERM if Windows would silently set a lower priority
+ (HIGH_PRIORITY_CLASS instead of REALTIME_PRIORITY_CLASS) due to
+ missing administrator privileges.
diff --git a/winsup/cygwin/sched.cc b/winsup/cygwin/sched.cc
index 71a1e868f..856def784 100644
--- a/winsup/cygwin/sched.cc
+++ b/winsup/cygwin/sched.cc
@@ -263,7 +263,7 @@ sched_setparam (pid_t pid, const struct sched_param *param)
set_errno (ESRCH);
return -1;
}
- if (!SetPriorityClass (process, pclass))
+ if (!set_and_check_winprio (process, pclass))
{
CloseHandle (process);
set_errno (EPERM);
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 433739cda..72537bc5a 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -3826,7 +3826,7 @@ setpriority (int which, id_t who, int value)
who = myself->pid;
if ((pid_t) who == myself->pid)
{
- if (!SetPriorityClass (GetCurrentProcess (), prio))
+ if (!set_and_check_winprio (GetCurrentProcess (), prio))
{
set_errno (EACCES);
return -1;
@@ -3875,7 +3875,7 @@ setpriority (int which, id_t who, int value)
error = EPERM;
else
{
- if (!SetPriorityClass (proc_h, prio))
+ if (!set_and_check_winprio (proc_h, prio))
error = EACCES;
else
p->nice = value;
--
2.45.1
More information about the Cygwin-patches
mailing list