seatd-user files
seatd launcher for a user
C 100%wget https://git.christianimmanuel.de/sway/seatd-user/archive/seatd-user.tar.gzseatd-user.c raw
/*
* seatd-user.c - minimal setuid-root wrapper to start/stop seatd for one user
*
* build: u=n76310; gcc -O2 -Wall -Wextra -DSEATD_USER="$u" seatd-user.c -o seatd-$u
* install: chown root:$u seatd-$u; chmod 4750 seatd-$u; mv seatd-$u /usr/bin/
*
* Only the group owner (the user) may execute it. seatd runs as root and
* hands its socket to SEATD_USER.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define STRINGIFY(x) #x
#define STRINGIFY2(x) STRINGIFY(x)
#ifndef SEATD_USER
#error "SEATD_USER not defined, build with -DSEATD_USER=<user>"
#endif
#define SEATD_USER_STRING STRINGIFY2(SEATD_USER)
#define SEATD_BIN "/usr/bin/seatd"
#define PKILL_BIN "/usr/bin/pkill"
/* fixed environment, nothing from the caller leaks into root context */
static char *const clean_env[] = { "PATH=/usr/bin:/bin", NULL };
/* make sure 0/1/2 are open so nothing we open later lands on them */
static void secure_std_fds(void)
{
for (int fd = 0; fd <= 2; fd++) {
if (fcntl(fd, F_GETFD) == -1 && errno == EBADF) {
int n = open("/dev/null", fd == 0 ? O_RDONLY : O_WRONLY);
if (n != fd)
_exit(1);
}
}
}
static int become_root(void)
{
if (setgid(0) != 0 || setuid(0) != 0) {
fprintf(stderr, "not running setuid root: %s\n", strerror(errno));
return -1;
}
return 0;
}
static int start_seatd(void)
{
char *const argv[] = { "seatd", "-u", SEATD_USER_STRING, NULL };
execve(SEATD_BIN, argv, clean_env);
fprintf(stderr, "exec %s: %s\n", SEATD_BIN, strerror(errno));
return 1;
}
static int stop_seatd(void)
{
char *const argv[] = { "pkill", "-x", "seatd", NULL };
int status;
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "fork: %s\n", strerror(errno));
return 1;
}
if (pid == 0) {
execve(PKILL_BIN, argv, clean_env);
fprintf(stderr, "exec %s: %s\n", PKILL_BIN, strerror(errno));
_exit(127);
}
if (waitpid(pid, &status, 0) < 0) {
fprintf(stderr, "waitpid: %s\n", strerror(errno));
return 1;
}
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
fprintf(stderr, "no running seatd or failed to stop it\n");
return 1;
}
return 0;
}
int main(int argc, char *argv[])
{
secure_std_fds();
if (argc != 2) {
fprintf(stderr, "Usage: %s start|stop\n", argv[0]);
return 1;
}
if (strcmp(argv[1], "start") != 0 && strcmp(argv[1], "stop") != 0) {
fprintf(stderr, "Invalid argument. Use 'start' or 'stop'\n");
return 1;
}
if (become_root() != 0)
return 1;
return strcmp(argv[1], "start") == 0 ? start_seatd() : stop_seatd();
}