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 */
|
/* applets[] is const, so we have to define this "override" structure */
|
||||||
static struct BB_suid_config {
|
static struct BB_suid_config {
|
||||||
int m_applet;
|
int m_applet;
|
||||||
uid_t m_uid;
|
struct bb_uidgid_t m_ugid;
|
||||||
gid_t m_gid;
|
|
||||||
mode_t m_mode;
|
mode_t m_mode;
|
||||||
struct BB_suid_config *m_next;
|
struct BB_suid_config *m_next;
|
||||||
} *suid_config;
|
} *suid_config;
|
||||||
@ -295,8 +294,6 @@ static const unsigned short mode_mask[] ALIGN2 = {
|
|||||||
0, S_IXOTH, S_IXOTH, 0 /* other */
|
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)
|
static void parse_config_file(void)
|
||||||
{
|
{
|
||||||
struct BB_suid_config *sct_head;
|
struct BB_suid_config *sct_head;
|
||||||
@ -312,8 +309,6 @@ static void parse_config_file(void)
|
|||||||
char buffer[256];
|
char buffer[256];
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
assert(!suid_config); /* Should be set to NULL by bss init. */
|
|
||||||
|
|
||||||
ruid = getuid();
|
ruid = getuid();
|
||||||
if (ruid == 0) /* run by root - don't need to even read config file */
|
if (ruid == 0) /* run by root - don't need to even read config file */
|
||||||
return;
|
return;
|
||||||
@ -322,7 +317,7 @@ static void parse_config_file(void)
|
|||||||
|| !S_ISREG(st.st_mode) /* Not a regular file? */
|
|| !S_ISREG(st.st_mode) /* Not a regular file? */
|
||||||
|| (st.st_uid != 0) /* Not owned by root? */
|
|| (st.st_uid != 0) /* Not owned by root? */
|
||||||
|| (st.st_mode & (S_IWGRP | S_IWOTH)) /* Writable by non-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;
|
return;
|
||||||
}
|
}
|
||||||
@ -335,10 +330,11 @@ static void parse_config_file(void)
|
|||||||
s = buffer;
|
s = buffer;
|
||||||
|
|
||||||
if (!fgets(s, sizeof(buffer), f)) { /* Are we done? */
|
if (!fgets(s, sizeof(buffer), f)) { /* Are we done? */
|
||||||
// why?
|
// Looks like bloat
|
||||||
if (ferror(f)) { /* Make sure it wasn't a read error. */
|
//if (ferror(f)) { /* Make sure it wasn't a read error. */
|
||||||
parse_error("reading");
|
// errmsg = "reading";
|
||||||
}
|
// goto pe_label;
|
||||||
|
//}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
suid_config = sct_head; /* Success, so set the pointer. */
|
suid_config = sct_head; /* Success, so set the pointer. */
|
||||||
return;
|
return;
|
||||||
@ -355,7 +351,8 @@ static void parse_config_file(void)
|
|||||||
* we do err on the side of caution. Besides, the line would be
|
* we do err on the side of caution. Besides, the line would be
|
||||||
* too long if it did end with a newline. */
|
* too long if it did end with a newline. */
|
||||||
if (!strchr(s, '\n') && !feof(f)) {
|
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
|
/* Trim leading and trailing whitespace, ignoring comments, and
|
||||||
@ -376,7 +373,8 @@ static void parse_config_file(void)
|
|||||||
|| e[1] /* Trailing characters? */
|
|| e[1] /* Trailing characters? */
|
||||||
|| !*(s = get_trimmed_slice(s+1, e)) /* Missing name? */
|
|| !*(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.
|
/* Right now we only have one section so just check it.
|
||||||
* If more sections are added in the future, please don't
|
* 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);
|
s = get_trimmed_slice(s, e);
|
||||||
}
|
}
|
||||||
if (!e || !*s) { /* Missing '=' or empty key. */
|
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
|
/* 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
|
* The last config line for each applet will be the
|
||||||
* one used since we insert at the head of the list.
|
* one used since we insert at the head of the list.
|
||||||
* I suppose this could be considered a feature. */
|
* 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_applet = applet_no;
|
||||||
sct->m_mode = 0;
|
/*sct->m_mode = 0;*/
|
||||||
sct->m_next = sct_head;
|
sct->m_next = sct_head;
|
||||||
sct_head = sct;
|
sct_head = sct;
|
||||||
|
|
||||||
@ -436,7 +435,8 @@ static void parse_config_file(void)
|
|||||||
const char *q;
|
const char *q;
|
||||||
q = strchrnul(mode_chars + 5*i, *e++);
|
q = strchrnul(mode_chars + 5*i, *e++);
|
||||||
if (!*q) {
|
if (!*q) {
|
||||||
parse_error("mode");
|
errmsg = "mode";
|
||||||
|
goto pe_label;
|
||||||
}
|
}
|
||||||
/* Adjust by -i to account for nul. */
|
/* Adjust by -i to account for nul. */
|
||||||
sct->m_mode |= mode_mask[(q - mode_chars) - i];
|
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
|
/* Note: we require whitespace between the mode and the
|
||||||
* user/group info. */
|
* user/group info. */
|
||||||
if ((s == e) || !(e = strchr(s, '.'))) {
|
if ((s == e) || !(e = strchr(s, '.'))) {
|
||||||
parse_error("<uid>.<gid>");
|
errmsg = "uid.gid";
|
||||||
}
|
goto pe_label;
|
||||||
*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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sct->m_gid = bb_strtoul(e, NULL, 10);
|
*e++ = ':'; /* get_uidgid doesn't understand user.group */
|
||||||
if (errno) {
|
if (get_uidgid(&sct->m_ugid, s, /*allow_numeric:*/ 1) == 0) {
|
||||||
struct group *grp;
|
errmsg = "unknown user/group";
|
||||||
grp = getgrnam(e);
|
goto pe_label;
|
||||||
if (!grp) {
|
|
||||||
parse_error("group");
|
|
||||||
}
|
|
||||||
sct->m_gid = grp->gr_gid;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -485,14 +470,14 @@ static void parse_config_file(void)
|
|||||||
* We may want to simply ignore such lines in case they
|
* We may want to simply ignore such lines in case they
|
||||||
* are used in some future version of busybox. */
|
* are used in some future version of busybox. */
|
||||||
if (!section) {
|
if (!section) {
|
||||||
parse_error("keyword outside section");
|
errmsg = "keyword outside section";
|
||||||
|
goto pe_label;
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* while (1) */
|
} /* while (1) */
|
||||||
|
|
||||||
pe_label:
|
pe_label:
|
||||||
fprintf(stderr, "Parse error in %s, line %d: %s\n",
|
bb_error_msg("parse error in %s, line %u: %s", config_file, lc, errmsg);
|
||||||
config_file, lc, errmsg);
|
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
/* Release any allocated memory before returning. */
|
/* Release any allocated memory before returning. */
|
||||||
@ -532,10 +517,10 @@ static void check_suid(int applet_no)
|
|||||||
goto check_need_suid;
|
goto check_need_suid;
|
||||||
found:
|
found:
|
||||||
m = sct->m_mode;
|
m = sct->m_mode;
|
||||||
if (sct->m_uid == ruid)
|
if (sct->m_ugid.uid == ruid)
|
||||||
/* same uid */
|
/* same uid */
|
||||||
m >>= 6;
|
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 */
|
/* same group / in group */
|
||||||
m >>= 3;
|
m >>= 3;
|
||||||
|
|
||||||
@ -544,7 +529,7 @@ static void check_suid(int applet_no)
|
|||||||
|
|
||||||
/* _both_ sgid and group_exec have to be set for setegid */
|
/* _both_ sgid and group_exec have to be set for setegid */
|
||||||
if ((sct->m_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
|
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 */
|
/* else (no setegid) we will set egid = rgid */
|
||||||
|
|
||||||
/* We set effective AND saved ids. If saved-id is not set
|
/* 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? */
|
/* do we have to set effective uid? */
|
||||||
uid = ruid;
|
uid = ruid;
|
||||||
if (sct->m_mode & S_ISUID)
|
if (sct->m_mode & S_ISUID)
|
||||||
uid = sct->m_uid;
|
uid = sct->m_ugid.uid;
|
||||||
/* else (no seteuid) we will set euid = ruid */
|
/* else (no seteuid) we will set euid = ruid */
|
||||||
|
|
||||||
if (setresuid(-1, uid, uid))
|
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);
|
gr = getgrnam(group);
|
||||||
if (!gr) return 0;
|
if (!gr)
|
||||||
|
return 0;
|
||||||
u->gid = gr->gr_gid;
|
u->gid = gr->gr_gid;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -292,7 +292,7 @@ static void make_device(char *path, int delete)
|
|||||||
* the rest the line unless keep_matching == 1 */
|
* the rest the line unless keep_matching == 1 */
|
||||||
|
|
||||||
/* 2nd field: uid:gid - device ownership */
|
/* 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);
|
bb_error_msg("unknown user/group %s on line %d", tokens[1], parser->lineno);
|
||||||
|
|
||||||
/* 3rd field: mode - device permissions */
|
/* 3rd field: mode - device permissions */
|
||||||
|
Loading…
Reference in New Issue
Block a user