From 09b57dfe286b5445e30815d752bf528da047e4df Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Wed, 6 Sep 2017 10:49:05 +0000 Subject: [PATCH] sysdep.c (__gnat_has_cap_sys_nice): New function to determine whether the current process has the CAP_SYS_NICE... 2017-09-06 Bob Duff * 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. From-SVN: r251777 --- gcc/ada/ChangeLog | 8 +++++ gcc/ada/s-taprop-linux.adb | 33 ++++++++++------- gcc/ada/sysdep.c | 72 +++++++++++++++++++++++++++++++++++++- 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,3 +1,11 @@ +2017-09-06 Bob Duff + + * 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 * a-comlin.ads, a-comlin.adb (Argument): Move the constraint 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 + +/* 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 -- 2.30.2