summaryrefslogtreecommitdiffstats
path: root/sysif.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-01-23 10:06:53 -0800
committerKaz Kylheku <kaz@kylheku.com>2016-01-23 10:06:53 -0800
commite080b5acbbe235d3ac32ccaf19826a8fd67e2eaf (patch)
treeb6abd783f6a63dabefc4f6c4174b0c10089c05df /sysif.c
parent7d250092d842e502bf5a571cefad999838997313 (diff)
downloadtxr-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.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/sysif.c b/sysif.c
index 18761e59..7b072072 100644
--- a/sysif.c
+++ b/sysif.c
@@ -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