simplify parsing of /etc/busybox.conf
function old new delta parse_config_file 799 667 -132 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
e0238f852b
commit
4566e172eb
@ -236,8 +236,7 @@ IF_FEATURE_SUID(static uid_t ruid;) /* real uid */
|
||||
/* applets[] is const, so we have to define this "override" structure */
|
||||
static struct BB_suid_config {
|
||||
int m_applet;
|
||||
uid_t m_uid;
|
||||
gid_t m_gid;
|
||||
struct bb_uidgid_t m_ugid;
|
||||
mode_t m_mode;
|
||||
struct BB_suid_config *m_next;
|
||||
} *suid_config;
|
||||
@ -295,8 +294,6 @@ static const unsigned short mode_mask[] ALIGN2 = {
|
||||
0, S_IXOTH, S_IXOTH, 0 /* other */
|
||||
};
|
||||
|
||||
#define parse_error(x) do { errmsg = x; goto pe_label; } while (0)
|
||||
|
||||
static void parse_config_file(void)
|
||||
{
|
||||
struct BB_suid_config *sct_head;
|
||||
@ -312,8 +309,6 @@ static void parse_config_file(void)
|
||||
char buffer[256];
|
||||
struct stat st;
|
||||
|
||||
assert(!suid_config); /* Should be set to NULL by bss init. */
|
||||
|
||||
ruid = getuid();
|
||||
if (ruid == 0) /* run by root - don't need to even read config file */
|
||||
return;
|
||||
@ -322,7 +317,7 @@ static void parse_config_file(void)
|
||||
|| !S_ISREG(st.st_mode) /* Not a regular file? */
|
||||
|| (st.st_uid != 0) /* Not owned by root? */
|
||||
|| (st.st_mode & (S_IWGRP | S_IWOTH)) /* Writable by non-root? */
|
||||
|| !(f = fopen_for_read(config_file)) /* Cannot open? */
|
||||
|| !(f = fopen_for_read(config_file)) /* Cannot open? */
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@ -335,10 +330,11 @@ static void parse_config_file(void)
|
||||
s = buffer;
|
||||
|
||||
if (!fgets(s, sizeof(buffer), f)) { /* Are we done? */
|
||||
// why?
|
||||
if (ferror(f)) { /* Make sure it wasn't a read error. */
|
||||
parse_error("reading");
|
||||
}
|
||||
// Looks like bloat
|
||||
//if (ferror(f)) { /* Make sure it wasn't a read error. */
|
||||
// errmsg = "reading";
|
||||
// goto pe_label;
|
||||
//}
|
||||
fclose(f);
|
||||
suid_config = sct_head; /* Success, so set the pointer. */
|
||||
return;
|
||||
@ -355,7 +351,8 @@ static void parse_config_file(void)
|
||||
* we do err on the side of caution. Besides, the line would be
|
||||
* too long if it did end with a newline. */
|
||||
if (!strchr(s, '\n') && !feof(f)) {
|
||||
parse_error("line too long");
|
||||
errmsg = "line too long";
|
||||
goto pe_label;
|
||||
}
|
||||
|
||||
/* Trim leading and trailing whitespace, ignoring comments, and
|
||||
@ -376,7 +373,8 @@ static void parse_config_file(void)
|
||||
|| e[1] /* Trailing characters? */
|
||||
|| !*(s = get_trimmed_slice(s+1, e)) /* Missing name? */
|
||||
) {
|
||||
parse_error("section header");
|
||||
errmsg = "section header";
|
||||
goto pe_label;
|
||||
}
|
||||
/* Right now we only have one section so just check it.
|
||||
* If more sections are added in the future, please don't
|
||||
@ -406,7 +404,8 @@ static void parse_config_file(void)
|
||||
s = get_trimmed_slice(s, e);
|
||||
}
|
||||
if (!e || !*s) { /* Missing '=' or empty key. */
|
||||
parse_error("keyword");
|
||||
errmsg = "keyword";
|
||||
goto pe_label;
|
||||
}
|
||||
|
||||
/* Ok, we have an applet name. Process the rhs if this
|
||||
@ -419,9 +418,9 @@ static void parse_config_file(void)
|
||||
* The last config line for each applet will be the
|
||||
* one used since we insert at the head of the list.
|
||||
* I suppose this could be considered a feature. */
|
||||
sct = xmalloc(sizeof(struct BB_suid_config));
|
||||
sct = xzalloc(sizeof(*sct));
|
||||
sct->m_applet = applet_no;
|
||||
sct->m_mode = 0;
|
||||
/*sct->m_mode = 0;*/
|
||||
sct->m_next = sct_head;
|
||||
sct_head = sct;
|
||||
|
||||
@ -436,7 +435,8 @@ static void parse_config_file(void)
|
||||
const char *q;
|
||||
q = strchrnul(mode_chars + 5*i, *e++);
|
||||
if (!*q) {
|
||||
parse_error("mode");
|
||||
errmsg = "mode";
|
||||
goto pe_label;
|
||||
}
|
||||
/* Adjust by -i to account for nul. */
|
||||
sct->m_mode |= mode_mask[(q - mode_chars) - i];
|
||||
@ -449,29 +449,14 @@ static void parse_config_file(void)
|
||||
/* Note: we require whitespace between the mode and the
|
||||
* user/group info. */
|
||||
if ((s == e) || !(e = strchr(s, '.'))) {
|
||||
parse_error("<uid>.<gid>");
|
||||
}
|
||||
*e++ = '\0';
|
||||
|
||||
/* We can't use get_ug_id here since it would exit()
|
||||
* if a uid or gid was not found. Oh well... */
|
||||
sct->m_uid = bb_strtoul(s, NULL, 10);
|
||||
if (errno) {
|
||||
struct passwd *pwd = getpwnam(s);
|
||||
if (!pwd) {
|
||||
parse_error("user");
|
||||
}
|
||||
sct->m_uid = pwd->pw_uid;
|
||||
errmsg = "uid.gid";
|
||||
goto pe_label;
|
||||
}
|
||||
|
||||
sct->m_gid = bb_strtoul(e, NULL, 10);
|
||||
if (errno) {
|
||||
struct group *grp;
|
||||
grp = getgrnam(e);
|
||||
if (!grp) {
|
||||
parse_error("group");
|
||||
}
|
||||
sct->m_gid = grp->gr_gid;
|
||||
*e++ = ':'; /* get_uidgid doesn't understand user.group */
|
||||
if (get_uidgid(&sct->m_ugid, s, /*allow_numeric:*/ 1) == 0) {
|
||||
errmsg = "unknown user/group";
|
||||
goto pe_label;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@ -485,14 +470,14 @@ static void parse_config_file(void)
|
||||
* We may want to simply ignore such lines in case they
|
||||
* are used in some future version of busybox. */
|
||||
if (!section) {
|
||||
parse_error("keyword outside section");
|
||||
errmsg = "keyword outside section";
|
||||
goto pe_label;
|
||||
}
|
||||
|
||||
} /* while (1) */
|
||||
|
||||
pe_label:
|
||||
fprintf(stderr, "Parse error in %s, line %d: %s\n",
|
||||
config_file, lc, errmsg);
|
||||
bb_error_msg("parse error in %s, line %u: %s", config_file, lc, errmsg);
|
||||
|
||||
fclose(f);
|
||||
/* Release any allocated memory before returning. */
|
||||
@ -532,10 +517,10 @@ static void check_suid(int applet_no)
|
||||
goto check_need_suid;
|
||||
found:
|
||||
m = sct->m_mode;
|
||||
if (sct->m_uid == ruid)
|
||||
if (sct->m_ugid.uid == ruid)
|
||||
/* same uid */
|
||||
m >>= 6;
|
||||
else if ((sct->m_gid == rgid) || ingroup(ruid, sct->m_gid))
|
||||
else if ((sct->m_ugid.gid == rgid) || ingroup(ruid, sct->m_ugid.gid))
|
||||
/* same group / in group */
|
||||
m >>= 3;
|
||||
|
||||
@ -544,7 +529,7 @@ static void check_suid(int applet_no)
|
||||
|
||||
/* _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_gid;
|
||||
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
|
||||
@ -555,7 +540,7 @@ static void check_suid(int applet_no)
|
||||
/* do we have to set effective uid? */
|
||||
uid = ruid;
|
||||
if (sct->m_mode & S_ISUID)
|
||||
uid = sct->m_uid;
|
||||
uid = sct->m_ugid.uid;
|
||||
/* else (no seteuid) we will set euid = ruid */
|
||||
|
||||
if (setresuid(-1, uid, uid))
|
||||
|
@ -71,7 +71,8 @@ int FAST_FUNC get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok)
|
||||
}
|
||||
}
|
||||
gr = getgrnam(group);
|
||||
if (!gr) return 0;
|
||||
if (!gr)
|
||||
return 0;
|
||||
u->gid = gr->gr_gid;
|
||||
}
|
||||
return 1;
|
||||
|
@ -292,7 +292,7 @@ static void make_device(char *path, int delete)
|
||||
* the rest the line unless keep_matching == 1 */
|
||||
|
||||
/* 2nd field: uid:gid - device ownership */
|
||||
if (get_uidgid(&ugid, tokens[1], 1) == 0)
|
||||
if (get_uidgid(&ugid, tokens[1], /*allow_numeric:*/ 1) == 0)
|
||||
bb_error_msg("unknown user/group %s on line %d", tokens[1], parser->lineno);
|
||||
|
||||
/* 3rd field: mode - device permissions */
|
||||
|
Loading…
Reference in New Issue
Block a user