Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 98481e79 authored by Len Brown's avatar Len Brown
Browse files

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: default avatarLen Brown <len.brown@intel.com>
parent bfa76d49
Loading
Loading
Loading
Loading
+41 −12
Original line number Diff line number Diff line
@@ -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()
{
	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)
		errx(-6, "must be root");
			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();