aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Config.in10
-rw-r--r--libbb/appletlib.c67
2 files changed, 43 insertions, 34 deletions
diff --git a/Config.in b/Config.in
index 38d8f0c53..b65fe4530 100644
--- a/Config.in
+++ b/Config.in
@@ -350,7 +350,15 @@ config FEATURE_SUID_CONFIG
by checking /etc/busybox.conf. (This is sort of a poor man's sudo.)
The format of this file is as follows:
- <applet> = [Ssx-][Ssx-][x-] (<username>|<uid>).(<groupname>|<gid>)
+ APPLET = [Ssx-][Ssx-][x-] USER.GROUP
+
+ s: This user/group are allowed to execute APPLET.
+ APPLET will run under USER or GROUP.
+ x: User/group/others are allowed to execute APPLET.
+ No UID/GID change will be done when it is run.
+ S: This user/group are NOT allowed to execute APPLET.
+ APPLET will run under USER or GROUP.
+ -: User/group/others are not allowed to execute APPLET.
An example might help:
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 269cc5bbf..ed60a1a0a 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -281,21 +281,11 @@ static char *get_trimmed_slice(char *s, char *e)
return skip_whitespace(s);
}
-/* Don't depend on the tools to combine strings. */
-static const char config_file[] ALIGN1 = "/etc/busybox.conf";
-
-/* We don't supply a value for the nul, so an index adjustment is
- * necessary below. Also, we use unsigned short here to save some
- * space even though these are really mode_t values. */
-static const unsigned short mode_mask[] ALIGN2 = {
- /* SST sst xxx --- */
- S_ISUID, S_ISUID|S_IXUSR, S_IXUSR, 0, /* user */
- S_ISGID, S_ISGID|S_IXGRP, S_IXGRP, 0, /* group */
- 0, S_IXOTH, S_IXOTH, 0 /* other */
-};
-
static void parse_config_file(void)
{
+ /* Don't depend on the tools to combine strings. */
+ static const char config_file[] ALIGN1 = "/etc/busybox.conf";
+
struct suid_config_t *sct_head;
int applet_no;
FILE *f;
@@ -411,7 +401,7 @@ static void parse_config_file(void)
* up when the busybox configuration is changed. */
applet_no = find_applet_by_name(s);
if (applet_no >= 0) {
- int i;
+ unsigned i;
struct suid_config_t *sct;
/* Note: We currently don't check for duplicates!
@@ -429,17 +419,24 @@ static void parse_config_file(void)
e = skip_whitespace(e+1);
for (i = 0; i < 3; i++) {
- /* There are 4 chars + 1 nul for each of user/group/other. */
- static const char mode_chars[] ALIGN1 = "Ssx-\0" "Ssx-\0" "Ttx-";
-
- const char *q;
- q = strchrnul(mode_chars + 5*i, *e++);
- if (!*q) {
+ /* There are 4 chars for each of user/group/other.
+ * "x-xx" instead of "x-" are to make
+ * "idx > 3" check catch invalid chars.
+ */
+ static const char mode_chars[] ALIGN1 = "Ssx-" "Ssx-" "x-xx";
+ static const unsigned short mode_mask[] ALIGN2 = {
+ S_ISUID, S_ISUID|S_IXUSR, S_IXUSR, 0, /* Ssx- */
+ S_ISGID, S_ISGID|S_IXGRP, S_IXGRP, 0, /* Ssx- */
+ S_IXOTH, 0 /* x- */
+ };
+ const char *q = strchrnul(mode_chars + 4*i, *e);
+ unsigned idx = q - (mode_chars + 4*i);
+ if (idx > 3) {
errmsg = "mode";
goto pe_label;
}
- /* Adjust by -i to account for nul. */
- sct->m_mode |= mode_mask[(q - mode_chars) - i];
+ sct->m_mode |= mode_mask[q - mode_chars];
+ e++;
}
/* Now get the user/group info. */
@@ -512,6 +509,7 @@ static void check_suid(int applet_no)
}
goto check_need_suid;
found:
+ /* Is this user allowed to run this applet? */
m = sct->m_mode;
if (sct->m_ugid.uid == ruid)
/* same uid */
@@ -519,28 +517,31 @@ static void check_suid(int applet_no)
else if ((sct->m_ugid.gid == rgid) || ingroup(ruid, sct->m_ugid.gid))
/* same group / in group */
m >>= 3;
-
- if (!(m & S_IXOTH)) /* is x bit not set ? */
+ if (!(m & S_IXOTH)) /* is x bit not set? */
bb_error_msg_and_die("you have no permission to run this applet!");
- /* _both_ sgid and group_exec have to be set for setegid */
- if ((sct->m_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
- rgid = sct->m_ugid.gid;
- /* else (no setegid) we will set egid = rgid */
-
/* We set effective AND saved ids. If saved-id is not set
- * like we do below, seteiud(0) can still later succeed! */
+ * like we do below, seteuid(0) can still later succeed! */
+
+ /* Are we directed to change gid
+ * (APPLET = *s* USER.GROUP or APPLET = *S* USER.GROUP)?
+ */
+ if (sct->m_mode & S_ISGID)
+ rgid = sct->m_ugid.gid;
+ /* else: we will set egid = rgid, thus dropping sgid effect */
if (setresgid(-1, rgid, rgid))
bb_perror_msg_and_die("setresgid");
- /* do we have to set effective uid? */
+ /* Are we directed to change uid
+ * (APPLET = s** USER.GROUP or APPLET = S** USER.GROUP)?
+ */
uid = ruid;
if (sct->m_mode & S_ISUID)
uid = sct->m_ugid.uid;
- /* else (no seteuid) we will set euid = ruid */
-
+ /* else: we will set euid = ruid, thus dropping suid effect */
if (setresuid(-1, uid, uid))
bb_perror_msg_and_die("setresuid");
+
goto ret;
}
# if !ENABLE_FEATURE_SUID_CONFIG_QUIET