diff options
author | Len Brown <len.brown@intel.com> | 2014-08-15 00:36:50 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2015-02-09 16:41:16 -0500 |
commit | 98481e79b60a50d699b79292ff1b7e56e7fa8425 (patch) | |
tree | 148ec049930bed66b08ccbfa1dcddc11ebd841c4 /tools | |
parent | bfa76d49576599a4b9f9b7a71f23d73d6dcff735 (diff) |
tools/power turbostat: relax dependency on root permission
For turbostat to run as non-root, it needs to permissions:
1. read access to /dev/cpu/*/msr
via standard user/group/world file permissions
2. CAP_SYS_RAWIO
eg. # setcap cap_sys_rawio=ep turbostat
Yes, running as root still works.
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 5b1b807265a1..6f29fc11fde6 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c | |||
@@ -38,6 +38,8 @@ | |||
38 | #include <ctype.h> | 38 | #include <ctype.h> |
39 | #include <sched.h> | 39 | #include <sched.h> |
40 | #include <cpuid.h> | 40 | #include <cpuid.h> |
41 | #include <linux/capability.h> | ||
42 | #include <errno.h> | ||
41 | 43 | ||
42 | char *proc_stat = "/proc/stat"; | 44 | char *proc_stat = "/proc/stat"; |
43 | unsigned int interval_sec = 5; /* set with -i interval_sec */ | 45 | unsigned int interval_sec = 5; /* set with -i interval_sec */ |
@@ -251,15 +253,13 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr) | |||
251 | sprintf(pathname, "/dev/cpu/%d/msr", cpu); | 253 | sprintf(pathname, "/dev/cpu/%d/msr", cpu); |
252 | fd = open(pathname, O_RDONLY); | 254 | fd = open(pathname, O_RDONLY); |
253 | if (fd < 0) | 255 | if (fd < 0) |
254 | return -1; | 256 | err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname); |
255 | 257 | ||
256 | retval = pread(fd, msr, sizeof *msr, offset); | 258 | retval = pread(fd, msr, sizeof *msr, offset); |
257 | close(fd); | 259 | close(fd); |
258 | 260 | ||
259 | if (retval != sizeof *msr) { | 261 | if (retval != sizeof *msr) |
260 | fprintf(stderr, "%s offset 0x%llx read failed\n", pathname, (unsigned long long)offset); | 262 | err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset); |
261 | return -1; | ||
262 | } | ||
263 | 263 | ||
264 | return 0; | 264 | return 0; |
265 | } | 265 | } |
@@ -1462,10 +1462,40 @@ void check_dev_msr() | |||
1462 | "Try \"# modprobe msr\""); | 1462 | "Try \"# modprobe msr\""); |
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | void check_super_user() | 1465 | void check_permissions() |
1466 | { | 1466 | { |
1467 | if (getuid() != 0) | 1467 | struct __user_cap_header_struct cap_header_data; |
1468 | errx(-6, "must be root"); | 1468 | cap_user_header_t cap_header = &cap_header_data; |
1469 | struct __user_cap_data_struct cap_data_data; | ||
1470 | cap_user_data_t cap_data = &cap_data_data; | ||
1471 | extern int capget(cap_user_header_t hdrp, cap_user_data_t datap); | ||
1472 | int do_exit = 0; | ||
1473 | |||
1474 | /* check for CAP_SYS_RAWIO */ | ||
1475 | cap_header->pid = getpid(); | ||
1476 | cap_header->version = _LINUX_CAPABILITY_VERSION; | ||
1477 | if (capget(cap_header, cap_data) < 0) | ||
1478 | err(-6, "capget(2) failed"); | ||
1479 | |||
1480 | if ((cap_data->effective & (1 << CAP_SYS_RAWIO)) == 0) { | ||
1481 | do_exit++; | ||
1482 | warnx("capget(CAP_SYS_RAWIO) failed," | ||
1483 | " try \"# setcap cap_sys_rawio=ep %s\"", progname); | ||
1484 | } | ||
1485 | |||
1486 | /* test file permissions */ | ||
1487 | if (euidaccess("/dev/cpu/0/msr", R_OK)) { | ||
1488 | do_exit++; | ||
1489 | warn("/dev/cpu/0/msr open failed, try chown or chmod +r /dev/cpu/*/msr"); | ||
1490 | } | ||
1491 | |||
1492 | /* if all else fails, thell them to be root */ | ||
1493 | if (do_exit) | ||
1494 | if (getuid() != 0) | ||
1495 | warnx("Or simply run as root"); | ||
1496 | |||
1497 | if (do_exit) | ||
1498 | exit(-6); | ||
1469 | } | 1499 | } |
1470 | 1500 | ||
1471 | int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) | 1501 | int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) |
@@ -2299,10 +2329,9 @@ void setup_all_buffers(void) | |||
2299 | 2329 | ||
2300 | void turbostat_init() | 2330 | void turbostat_init() |
2301 | { | 2331 | { |
2302 | check_cpuid(); | ||
2303 | |||
2304 | check_dev_msr(); | 2332 | check_dev_msr(); |
2305 | check_super_user(); | 2333 | check_permissions(); |
2334 | check_cpuid(); | ||
2306 | 2335 | ||
2307 | setup_all_buffers(); | 2336 | setup_all_buffers(); |
2308 | 2337 | ||
@@ -2441,7 +2470,7 @@ int main(int argc, char **argv) | |||
2441 | cmdline(argc, argv); | 2470 | cmdline(argc, argv); |
2442 | 2471 | ||
2443 | if (verbose) | 2472 | if (verbose) |
2444 | fprintf(stderr, "turbostat v3.7 Feb 6, 2014" | 2473 | fprintf(stderr, "turbostat v3.8 14-Aug 2014" |
2445 | " - Len Brown <lenb@kernel.org>\n"); | 2474 | " - Len Brown <lenb@kernel.org>\n"); |
2446 | 2475 | ||
2447 | turbostat_init(); | 2476 | turbostat_init(); |