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>
This commit is contained in:
		
							parent
							
								
									bfa76d4957
								
							
						
					
					
						commit
						98481e79b6
					
				| @ -38,6 +38,8 @@ | ||||
| #include <ctype.h> | ||||
| #include <sched.h> | ||||
| #include <cpuid.h> | ||||
| #include <linux/capability.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| char *proc_stat = "/proc/stat"; | ||||
| 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) | ||||
| 	sprintf(pathname, "/dev/cpu/%d/msr", cpu); | ||||
| 	fd = open(pathname, O_RDONLY); | ||||
| 	if (fd < 0) | ||||
| 		return -1; | ||||
| 		err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname); | ||||
| 
 | ||||
| 	retval = pread(fd, msr, sizeof *msr, offset); | ||||
| 	close(fd); | ||||
| 
 | ||||
| 	if (retval != sizeof *msr) { | ||||
| 		fprintf(stderr, "%s offset 0x%llx read failed\n", pathname, (unsigned long long)offset); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (retval != sizeof *msr) | ||||
| 		err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| @ -1462,10 +1462,40 @@ void check_dev_msr() | ||||
| 		    "Try \"# modprobe msr\""); | ||||
| } | ||||
| 
 | ||||
| void check_super_user() | ||||
| void check_permissions() | ||||
| { | ||||
| 	if (getuid() != 0) | ||||
| 		errx(-6, "must be root"); | ||||
| 	struct __user_cap_header_struct cap_header_data; | ||||
| 	cap_user_header_t cap_header = &cap_header_data; | ||||
| 	struct __user_cap_data_struct cap_data_data; | ||||
| 	cap_user_data_t cap_data = &cap_data_data; | ||||
| 	extern int capget(cap_user_header_t hdrp, cap_user_data_t datap); | ||||
| 	int do_exit = 0; | ||||
| 
 | ||||
| 	/* check for CAP_SYS_RAWIO */ | ||||
| 	cap_header->pid = getpid(); | ||||
| 	cap_header->version = _LINUX_CAPABILITY_VERSION; | ||||
| 	if (capget(cap_header, cap_data) < 0) | ||||
| 		err(-6, "capget(2) failed"); | ||||
| 
 | ||||
| 	if ((cap_data->effective & (1 << CAP_SYS_RAWIO)) == 0) { | ||||
| 		do_exit++; | ||||
| 		warnx("capget(CAP_SYS_RAWIO) failed," | ||||
| 			" try \"# setcap cap_sys_rawio=ep %s\"", progname); | ||||
| 	} | ||||
| 
 | ||||
| 	/* test file permissions */ | ||||
| 	if (euidaccess("/dev/cpu/0/msr", R_OK)) { | ||||
| 		do_exit++; | ||||
| 		warn("/dev/cpu/0/msr open failed, try chown or chmod +r /dev/cpu/*/msr"); | ||||
| 	} | ||||
| 
 | ||||
| 	/* if all else fails, thell them to be root */ | ||||
| 	if (do_exit) | ||||
| 		if (getuid() != 0) | ||||
| 			warnx("Or simply run as root"); | ||||
| 
 | ||||
| 	if (do_exit) | ||||
| 		exit(-6); | ||||
| } | ||||
| 
 | ||||
| int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) | ||||
| @ -2299,10 +2329,9 @@ void setup_all_buffers(void) | ||||
| 
 | ||||
| void turbostat_init() | ||||
| { | ||||
| 	check_cpuid(); | ||||
| 
 | ||||
| 	check_dev_msr(); | ||||
| 	check_super_user(); | ||||
| 	check_permissions(); | ||||
| 	check_cpuid(); | ||||
| 
 | ||||
| 	setup_all_buffers(); | ||||
| 
 | ||||
| @ -2441,7 +2470,7 @@ int main(int argc, char **argv) | ||||
| 	cmdline(argc, argv); | ||||
| 
 | ||||
| 	if (verbose) | ||||
| 		fprintf(stderr, "turbostat v3.7 Feb 6, 2014" | ||||
| 		fprintf(stderr, "turbostat v3.8 14-Aug 2014" | ||||
| 			" - Len Brown <lenb@kernel.org>\n"); | ||||
| 
 | ||||
| 	turbostat_init(); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user