diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-01-23 10:06:53 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-01-23 10:06:53 -0800 |
commit | e080b5acbbe235d3ac32ccaf19826a8fd67e2eaf (patch) | |
tree | b6abd783f6a63dabefc4f6c4174b0c10089c05df /sysif.c | |
parent | 7d250092d842e502bf5a571cefad999838997313 (diff) | |
download | txr-e080b5acbbe235d3ac32ccaf19826a8fd67e2eaf.tar.gz txr-e080b5acbbe235d3ac32ccaf19826a8fd67e2eaf.tar.bz2 txr-e080b5acbbe235d3ac32ccaf19826a8fd67e2eaf.zip |
Support setuid operation.
* sysif.c (orig_euid, real_uid, repress_called, is_setuid):
New static variables.
(repress_privilege, drop_privilage, simulate_setuid):
New functions.
(RC_MAGIC): New preprocessor symbol.
* sysif.c (repress_privilege, drop_privilage,
simulate_setuid): Declared.
* txr.c (txr_main): Call repress_privilege to check
and remember whether we are in setuid mode, and temporarily
drop the effective uid to the real one.
(txr_main): Permanently drop privileges in all cases except
script execution. In script execution cases, go through
simulate_setuid to either set or preserve the effective
user ID, or else drop privs.
* txr.1: Documented setuid operation in new section.
Diffstat (limited to 'sysif.c')
-rw-r--r-- | sysif.c | 53 |
1 files changed, 53 insertions, 0 deletions
@@ -861,6 +861,59 @@ static val setegid_wrap(val nval) return t; } +#define RC_MAGIC 0xbe50c001 + +static uid_t orig_euid, real_uid; +static int repress_called = 0, is_setuid = 1; + +void repress_privilege(void) +{ + real_uid = getuid(); + orig_euid = geteuid(); + + if (real_uid != orig_euid) + seteuid(getuid()); + else + is_setuid = 0; + + repress_called = RC_MAGIC; +} + +void drop_privilege(void) +{ + if (repress_called != RC_MAGIC || (is_setuid && setuid(getuid()) != 0)) + abort(); +} + +void simulate_setuid(val open_script) +{ + if (repress_called != RC_MAGIC || (is_setuid && seteuid(orig_euid) != 0)) + abort(); + + if (!is_setuid && orig_euid != 0) + return; + + { + val fdv = stream_get_prop(open_script, fd_k); + + if (fdv) { + struct stat stb; + cnum fd = c_num(fdv); + + if (fstat(fd, &stb) != 0) + abort(); + + if ((stb.st_mode & (S_ISUID | S_IXUSR)) == (S_ISUID | S_IXUSR)) { + seteuid(stb.st_uid); + return; + } + } + } + + if (is_setuid) + setuid(real_uid); +} + #endif #if HAVE_PWUID |