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:
Denys Vlasenko 2011-05-16 00:01:08 +02:00
parent e0238f852b
commit 4566e172eb
3 changed files with 33 additions and 47 deletions

View File

@ -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))

View File

@ -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;

View File

@ -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 */