Skip to content

Instantly share code, notes, and snippets.

@marcelog
Forked from hirose31/pathexec_run.c
Created June 19, 2017 18:13
Show Gist options
  • Save marcelog/5bd71222bd6170aedb4ae433c5b51c9a to your computer and use it in GitHub Desktop.
Save marcelog/5bd71222bd6170aedb4ae433c5b51c9a to your computer and use it in GitHub Desktop.
setuidgid + supplementary groups
/* Public domain. */
#include "error.h"
#include "stralloc.h"
#include "str.h"
#include "env.h"
#include "pathexec.h"
static stralloc tmp;
void pathexec_run(const char *file,const char * const *argv,const char * const *envp)
{
const char *path;
unsigned int split;
int savederrno;
if (file[str_chr(file,'/')]) {
execve(file,argv,envp);
return;
}
path = env_get("PATH");
if (!path) path = "/bin:/usr/bin";
savederrno = 0;
for (;;) {
split = str_chr(path,':');
if (!stralloc_copyb(&tmp,path,split)) return;
if (!split)
if (!stralloc_cats(&tmp,".")) return;
if (!stralloc_cats(&tmp,"/")) return;
if (!stralloc_cats(&tmp,file)) return;
if (!stralloc_0(&tmp)) return;
execve(tmp.s,argv,envp);
if (errno != error_noent) {
savederrno = errno;
if ((errno != error_acces) && (errno != error_perm) && (errno != error_isdir)) return;
}
if (!path[split]) {
if (savederrno) errno = savederrno;
return;
}
path += split;
path += 1;
}
}
/* Public domain. */
#include "hasshsgr.h"
#include "prot.h"
int prot_gid(int gid)
{
#ifdef HASSHORTSETGROUPS
short x[2];
x[0] = gid; x[1] = 73; /* catch errors */
if (setgroups(1,x) == -1) return -1;
#else
if (setgroups(1,&gid) == -1) return -1;
#endif
return setgid(gid); /* _should_ be redundant, but on some systems it isn't */
}
int prot_uid(int uid)
{
return setuid(uid);
}
#include <sys/types.h>
#include <pwd.h>
#include "prot.h"
#include "strerr.h"
#include "pathexec.h"
#include <grp.h>
#define FATAL "setuidgid: fatal: "
const char *account;
struct passwd *pw;
int main(int argc,const char *const *argv,const char *const *envp)
{
account = *++argv;
if (!account || !*++argv)
strerr_die1x(100,"setuidgid: usage: setuidgid account child");
pw = getpwnam(account);
if (!pw)
strerr_die3x(111,FATAL,"unknown account ",account);
if (prot_gid(pw->pw_gid) == -1)
strerr_die2sys(111,FATAL,"unable to setgid: ");
if (initgroups(account, pw->pw_gid) == -1)
strerr_die2sys(111,FATAL,"unable to initgroups: ");
if (prot_uid(pw->pw_uid) == -1)
strerr_die2sys(111,FATAL,"unable to setuid: ");
pathexec_run(*argv,argv,envp);
strerr_die4sys(111,FATAL,"unable to run ",*argv,": ");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment