summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2017-09-06 10:49:05 +0000
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2017-09-06 10:49:05 +0000
commitb2e61b1a74cf4ebfcb3cc81118ef9dae64cf1e57 (patch)
tree6d4aca5f0a54998aa02db1d4b6db9fac20fe075a
parentd49bc1d926e0d43984c151b2634fc35e1d70eb78 (diff)
downloadgcc-b2e61b1a74cf4ebfcb3cc81118ef9dae64cf1e57.tar.gz
2017-09-06 Bob Duff <duff@adacore.com>
* sysdep.c (__gnat_has_cap_sys_nice): New function to determine whether the current process has the CAP_SYS_NICE capability. * s-taprop-linux.adb (Get_Ceiling_Support): Update this to allow ceiling priorities if the current process has the CAP_SYS_NICE capability. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@251777 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ada/ChangeLog8
-rw-r--r--gcc/ada/s-taprop-linux.adb33
-rw-r--r--gcc/ada/sysdep.c72
3 files changed, 100 insertions, 13 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 7a146be789c..f914d238901 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,5 +1,13 @@
2017-09-06 Bob Duff <duff@adacore.com>
+ * sysdep.c (__gnat_has_cap_sys_nice): New function to determine
+ whether the current process has the CAP_SYS_NICE capability.
+ * s-taprop-linux.adb (Get_Ceiling_Support): Update this to allow
+ ceiling priorities if the current process has the CAP_SYS_NICE
+ capability.
+
+2017-09-06 Bob Duff <duff@adacore.com>
+
* a-comlin.ads, a-comlin.adb (Argument): Move the constraint
check back to the body, because SPARK is not yet ready for
"or else raise Constraint_Error".
diff --git a/gcc/ada/s-taprop-linux.adb b/gcc/ada/s-taprop-linux.adb
index 1d829de6ee0..cc49205cf0a 100644
--- a/gcc/ada/s-taprop-linux.adb
+++ b/gcc/ada/s-taprop-linux.adb
@@ -165,6 +165,13 @@ package body System.Task_Primitives.Operations is
pragma Import
(C, GNAT_pthread_condattr_setup, "__gnat_pthread_condattr_setup");
+ function GNAT_has_cap_sys_nice return C.int;
+ pragma Import
+ (C, GNAT_has_cap_sys_nice, "__gnat_has_cap_sys_nice");
+ -- We do not have pragma Linker_Options ("-lcap"); here, because this
+ -- library is not present on many Linux systems. 'libcap' is the Linux
+ -- "capabilities" library, called by __gnat_has_cap_sys_nice.
+
function Prio_To_Linux_Prio (Prio : Any_Priority) return C.int is
(C.int (Prio) + 1);
-- Convert Ada priority to Linux priority. Priorities are 1 .. 99 on
@@ -172,24 +179,26 @@ package body System.Task_Primitives.Operations is
function Get_Ceiling_Support return Boolean;
-- Get the value of the Ceiling_Support constant (see below).
- -- ???For now, we're returning True only if running as superuser,
- -- and ignore capabilities.
+ -- Note well: If this function or related code is modified, it should be
+ -- tested by hand, because automated testing doesn't exercise it.
function Get_Ceiling_Support return Boolean is
Ceiling_Support : Boolean := False;
begin
- if Locking_Policy = 'C' then
- declare
- function geteuid return Integer;
- pragma Import (C, geteuid, "geteuid");
- Superuser : constant Boolean := geteuid = 0;
- begin
- if Superuser then
- Ceiling_Support := True;
- end if;
- end;
+ if Locking_Policy /= 'C' then
+ return False;
end if;
+ declare
+ function geteuid return Integer;
+ pragma Import (C, geteuid, "geteuid");
+ Superuser : constant Boolean := geteuid = 0;
+ Has_Cap : constant C.int := GNAT_has_cap_sys_nice;
+ pragma Assert (Has_Cap in 0 | 1);
+ begin
+ Ceiling_Support := Superuser or else Has_Cap = 1;
+ end;
+
return Ceiling_Support;
end Get_Ceiling_Support;
diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c
index 679c70a77f7..64278fd8f38 100644
--- a/gcc/ada/sysdep.c
+++ b/gcc/ada/sysdep.c
@@ -6,7 +6,7 @@
* *
* C Implementation File *
* *
- * Copyright (C) 1992-2016, Free Software Foundation, Inc. *
+ * Copyright (C) 1992-2017, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
@@ -919,6 +919,76 @@ __gnat_is_file_not_found_error (int errno_val) {
}
}
+#if defined (__linux__)
+
+/* HAVE_CAPABILITY is defined if sys/capability.h exists on the system where
+ this is being compiled.
+*/
+
+#if defined (HAVE_CAPABILITY)
+#include <sys/capability.h>
+
+/* Note well: If this code is modified, it should be tested by hand,
+ because automated testing doesn't exercise it.
+*/
+
+/* __gnat_has_cap_sys_nice returns 1 if the current process has the
+ CAP_SYS_NICE capability. This capability is necessary to use the
+ Ceiling_Locking policy. Returns 0 otherwise. Note that this is
+ defined only for Linux.
+*/
+
+/* Define these as weak symbols, so if support for capabilities is not present,
+ programs can still link. On Ubuntu, support for capabilities can be
+ installed via "sudo apt-get --assume-yes install libcap-dev".
+ In addition, the user must link with "-lcap", or else these
+ symbols will be 0, and __gnat_has_cap_sys_nice will return 0.
+*/
+
+static cap_t cap_get_proc_weak() __attribute__ ((weakref ("cap_get_proc")));
+static int cap_get_flag_weak() __attribute__ ((weakref ("cap_get_flag")));
+static int cap_free_weak() __attribute__ ((weakref ("cap_free")));
+
+int
+__gnat_has_cap_sys_nice () {
+ /* If the address of cap_get_proc_weak is 0, this means support for
+ capabilities is not present, so we return 0. */
+ if (&cap_get_proc_weak == 0)
+ return 0;
+
+ cap_t caps = cap_get_proc_weak();
+ cap_flag_value_t value;
+
+ if (caps == NULL)
+ return 0;
+
+ if (cap_get_flag_weak(caps, CAP_SYS_NICE, CAP_EFFECTIVE, &value) == -1)
+ return 0;
+
+ if (cap_free_weak(caps) == -1)
+ return 0;
+
+ if (value == CAP_SET)
+ return 1;
+
+ return 0;
+}
+
+#else
+
+/* HAVE_CAPABILITY is not defined, so sys/capability.h does not exist, so
+ simply indicate that the current process does not have the CAP_SYS_NICE
+ capability.
+*/
+
+int
+__gnat_has_cap_sys_nice () {
+ return 0;
+}
+
+#endif
+#endif
+
#ifdef __ANDROID__
/* Provide extern symbols for sig* as needed by the tasking run-time, instead