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
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;
* *
* 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- *
}
}
+#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