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:
		| @@ -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 */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user