mirror of
https://github.com/troglobit/finit.git
synced 2026-10-24 11:54:36 +00:00
initramfs: reject a non-regular init and an overlong init path
The precheck accepts a directory as new init: access(path, X_OK) only checks search permission, which directories almost always have, so the mistake is not caught until after teardown. The snprintf() building init_path also never checks for truncation, so an overlong newroot + newinit validates the wrong path. Require a regular file, with EISDIR or ENOEXEC to match what is printed, and fail with ENAMETOOLONG on a truncated init path. Signed-off-by: Paweł Sobczak <github@fixeq.qzz.io>
This commit is contained in:
1 parent
42840f0f36
commit
7263641953
1 file changed
+18
-3
+18
-3
@@ -170,7 +170,7 @@ switch_root_fail(char *errbuf, size_t errbuflen, int err, const char *fmt, ...)
|
||||
int switch_root_precheck(const char *newroot, const char *newinit,
|
||||
char *errbuf, size_t errbuflen)
|
||||
{
|
||||
struct stat newroot_st, oldroot_st;
|
||||
struct stat newroot_st, oldroot_st, st;
|
||||
char init_path[PATH_MAX];
|
||||
int fd;
|
||||
|
||||
@@ -218,12 +218,27 @@ int switch_root_precheck(const char *newroot, const char *newinit,
|
||||
return switch_root_fail(errbuf, errbuflen, EINVAL,
|
||||
"%s is not a mount point", newroot);
|
||||
|
||||
/* Verify init exists in new root */
|
||||
snprintf(init_path, sizeof(init_path), "%s%s", newroot, newinit);
|
||||
/* Verify init exists in new root and is a regular file */
|
||||
if (paste(init_path, sizeof(init_path),
|
||||
newroot, newinit) >= (int)sizeof(init_path))
|
||||
return switch_root_fail(errbuf, errbuflen, ENAMETOOLONG,
|
||||
"init path too long");
|
||||
|
||||
if (access(init_path, X_OK))
|
||||
return switch_root_fail(errbuf, errbuflen, ENOENT,
|
||||
"%s not found or not executable", init_path);
|
||||
|
||||
if (stat(init_path, &st))
|
||||
return switch_root_fail(errbuf, errbuflen, errno,
|
||||
"cannot stat %s: %s", init_path, strerror(errno));
|
||||
if (S_ISDIR(st.st_mode))
|
||||
return switch_root_fail(errbuf, errbuflen, EISDIR,
|
||||
"%s is a directory, not init", init_path);
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return switch_root_fail(errbuf, errbuflen, ENOEXEC,
|
||||
"%s is not a regular file", init_path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user