Merge branch 'caps' of https://github.com/ericonr/util-linux
* 'caps' of https://github.com/ericonr/util-linux: lib/caputils: add fall back for last cap using prctl. lib/procutils: add proc_is_procfs helper.
This commit is contained in:
commit
61dc5ae39a
|
@ -2,6 +2,7 @@
|
|||
#define UTIL_LINUX_PROCUTILS
|
||||
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct proc_tasks {
|
||||
DIR *dir;
|
||||
|
@ -31,4 +32,6 @@ extern int proc_next_pid(struct proc_processes *ps, pid_t *pid);
|
|||
extern char *proc_get_command(pid_t pid);
|
||||
extern char *proc_get_command_name(pid_t pid);
|
||||
|
||||
extern int proc_is_procfs(int fd);
|
||||
|
||||
#endif /* UTIL_LINUX_PROCUTILS */
|
||||
|
|
|
@ -14,32 +14,59 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <sys/prctl.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "caputils.h"
|
||||
#include "procutils.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
static int test_cap(unsigned int cap)
|
||||
{
|
||||
/* prctl returns 0 or 1 for valid caps, -1 otherwise */
|
||||
return prctl(PR_CAPBSET_READ, cap, 0, 0, 0) >= 0;
|
||||
}
|
||||
|
||||
int cap_last_cap(void)
|
||||
{
|
||||
/* CAP_LAST_CAP is untrustworthy. */
|
||||
static int ret = -1;
|
||||
int matched;
|
||||
static int cap = -1;
|
||||
FILE *f;
|
||||
|
||||
if (ret != -1)
|
||||
return ret;
|
||||
if (cap != -1)
|
||||
return cap;
|
||||
|
||||
/* try to read value from kernel, check that the path is
|
||||
* indeed in a procfs mount */
|
||||
f = fopen(_PATH_PROC_CAPLASTCAP, "r");
|
||||
if (!f) {
|
||||
ret = CAP_LAST_CAP; /* guess */
|
||||
return ret;
|
||||
if (f) {
|
||||
int matched = 0;
|
||||
|
||||
if (proc_is_procfs(fileno(f))) {
|
||||
matched = fscanf(f, "%d", &cap);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
/* we check if the cap after this one really isn't valid */
|
||||
if (matched == 1 && cap < INT_MAX && !test_cap(cap + 1))
|
||||
return cap;
|
||||
}
|
||||
|
||||
matched = fscanf(f, "%d", &ret);
|
||||
fclose(f);
|
||||
/* if it wasn't possible to read the file in /proc,
|
||||
* fall back to binary search over capabilities */
|
||||
|
||||
if (matched != 1)
|
||||
ret = CAP_LAST_CAP; /* guess */
|
||||
/* starting with cap=INT_MAX means we always know
|
||||
* that cap1 is invalid after the first iteration */
|
||||
unsigned int cap0 = 0, cap1 = INT_MAX;
|
||||
cap = INT_MAX;
|
||||
while ((int)cap0 < cap) {
|
||||
if (test_cap(cap)) {
|
||||
cap0 = cap;
|
||||
} else {
|
||||
cap1 = cap;
|
||||
}
|
||||
cap = (cap0 + cap1) / 2U;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return cap;
|
||||
}
|
||||
|
|
|
@ -13,11 +13,13 @@
|
|||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "procutils.h"
|
||||
#include "statfs_magic.h"
|
||||
#include "fileutils.h"
|
||||
#include "all-io.h"
|
||||
#include "c.h"
|
||||
|
@ -235,6 +237,23 @@ int proc_next_pid(struct proc_processes *ps, pid_t *pid)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* checks if fd is file in a procfs;
|
||||
* returns 1 if true, 0 if false or couldn't determine */
|
||||
int proc_is_procfs(int fd)
|
||||
{
|
||||
struct statfs st;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
ret = fstatfs(fd, &st);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
|
||||
if (ret == 0)
|
||||
return st.f_type == STATFS_PROC_MAGIC;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM_PROCUTILS
|
||||
|
||||
static int test_tasks(int argc, char *argv[])
|
||||
|
|
Loading…
Reference in New Issue