删除root权限

我有一个守护进程开始作为根(所以它可以绑定到低端口)。 初始化之后,我非常希望为了安全起见而放弃root权限。

任何人都可以指向我在一个已知的正确的一段代码在C这将做到这一点?

我已经阅读了手册页,我已经在不同的应用程序中查看了这些手册的各种实现,它们都是不同的,其中一些非常复杂。 这是与安全相关的代码,我真的不希望重蹈其他人的同样的错误。 我正在寻找的是一个最好的实践,已知的好的,可移植的库函数,我可以使用的知识,它会得到它的权利。 这样的事情存在吗?

作为参考:我以root身份开始; 我需要改变在不同的用户和gid下运行; 我需要有补充小组正确设置; 之后我不需要改回根权限。

你正在寻找这篇文章:

POS36-C。 在放弃特权的同时观察正确的撤销命令

不知道如何最好地把一些信息,而不复制该网页的内容…

为了删除所有权限(用户和组),您需要在用户之前删除组。 假设useridgroupid包含用户和组的ID,并且假定有效ID也是root,则通过调用setuid()和setgid()来完成 :

 if (getuid() == 0) { /* process is running as root, drop privileges */ if (setgid(groupid) != 0) fatal("setgid: Unable to drop group privileges: %s", strerror(errno)); if (setuid(userid) != 0) fatal("setuid: Unable to drop user privileges: %S", strerror(errno)); } 

如果你是偏执的人,你可以尝试获得你的root权限,这应该会失败。 如果它没有失败,你救助:

  if (setuid(0) != -1) fatal("ERROR: Managed to regain root privileges?"); 

另外,如果你仍然偏执狂,你可能也想seteuid()和setegid() ,但它不应该是必要的,因为setuid()和setgid()已经设置所有的ID,如果进程是由root拥有的。

补充组列表是一个问题,因为没有POSIX函数来设置补充组(有getgroups() ,但没有setgroups())。 有一个BSD和Linux扩展setgroups() ,你可以使用它,这关系到你。

您还应该chdir("/")或任何其他目录,以便进程不会保留在根目录中。

因为你的问题一般是关于Unix的,所以这是一般的方法。 请注意,在Linux中,这不再是首选的方法。 在当前的Linux版本中,您应该在可执行文件上设置CAP_NET_BIND_SERVICEfunction ,并以普通用户身份运行它。 不需要root权限。

这是我最擅长的:

 #define _GNU_SOURCE // for secure_getenv() int drop_root_privileges(void) { // returns 0 on success and -1 on failure gid_t gid; uid_t uid; // no need to "drop" the privileges that you don't have in the first place! if (getuid() != 0) { return 0; } // when your program is invoked with sudo, getuid() will return 0 and you // won't be able to drop your privileges if ((uid = getuid()) == 0) { const char *sudo_uid = secure_getenv("SUDO_UID"); if (sudo_uid == NULL) { printf("environment variable `SUDO_UID` not found\n"); return -1; } errno = 0; uid = (uid_t) strtoll(sudo_uid, NULL, 10); if (errno != 0) { perror("under-/over-flow in converting `SUDO_UID` to integer"); return -1; } } // again, in case your program is invoked using sudo if ((gid = getgid()) == 0) { const char *sudo_gid = secure_getenv("SUDO_GID"); if (sudo_gid == NULL) { printf("environment variable `SUDO_GID` not found\n"); return -1; } errno = 0; gid = (gid_t) strtoll(sudo_gid, NULL, 10); if (errno != 0) { perror("under-/over-flow in converting `SUDO_GID` to integer"); return -1; } } if (setgid(gid) != 0) { perror("setgid"); return -1; } if (setuid(uid) != 0) { perror("setgid"); return -1; } // change your directory to somewhere else, just in case if you are in a // root-owned one (eg /root) if (chdir("/") != 0) { perror("chdir"); return -1; } // check if we successfully dropped the root privileges if (setuid(0) == 0 || seteuid(0) == 0) { printf("could not drop root privileges!\n"); return -1; } return 0; }