Skip to content

Commit

Permalink
[PATCH] initramfs overwrite fix
Browse files Browse the repository at this point in the history
This patch ensures that initramfs overwrites work correctly, even when dealing
with device nodes of different types.  Furthermore, when replacing a file
which already exists, we must make very certain that we truncate the existing
file.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Cc: Michael Neuling <mikey@neuling.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
H. Peter Anvin authored and Linus Torvalds committed Jun 26, 2006
1 parent 0538195 commit 2139a7f
Showing 1 changed file with 30 additions and 6 deletions.
36 changes: 30 additions & 6 deletions init/initramfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ static void __init free(void *where)

static __initdata struct hash {
int ino, minor, major;
mode_t mode;
struct hash *next;
char name[N_ALIGN(PATH_MAX)];
} *head[32];
Expand All @@ -41,7 +42,8 @@ static inline int hash(int major, int minor, int ino)
return tmp & 31;
}

static char __init *find_link(int major, int minor, int ino, char *name)
static char __init *find_link(int major, int minor, int ino,
mode_t mode, char *name)
{
struct hash **p, *q;
for (p = head + hash(major, minor, ino); *p; p = &(*p)->next) {
Expand All @@ -51,14 +53,17 @@ static char __init *find_link(int major, int minor, int ino, char *name)
continue;
if ((*p)->major != major)
continue;
if (((*p)->mode ^ mode) & S_IFMT)
continue;
return (*p)->name;
}
q = (struct hash *)malloc(sizeof(struct hash));
if (!q)
panic("can't allocate link hash entry");
q->ino = ino;
q->minor = minor;
q->major = major;
q->minor = minor;
q->ino = ino;
q->mode = mode;
strcpy(q->name, name);
q->next = NULL;
*p = q;
Expand Down Expand Up @@ -229,13 +234,25 @@ static int __init do_reset(void)
static int __init maybe_link(void)
{
if (nlink >= 2) {
char *old = find_link(major, minor, ino, collected);
char *old = find_link(major, minor, ino, mode, collected);
if (old)
return (sys_link(old, collected) < 0) ? -1 : 1;
}
return 0;
}

static void __init clean_path(char *path, mode_t mode)
{
struct stat st;

if (!sys_newlstat(path, &st) && (st.st_mode^mode) & S_IFMT) {
if (S_ISDIR(st.st_mode))
sys_rmdir(path);
else
sys_unlink(path);
}
}

static __initdata int wfd;

static int __init do_name(void)
Expand All @@ -248,9 +265,15 @@ static int __init do_name(void)
}
if (dry_run)
return 0;
clean_path(collected, mode);
if (S_ISREG(mode)) {
if (maybe_link() >= 0) {
wfd = sys_open(collected, O_WRONLY|O_CREAT, mode);
int ml = maybe_link();
if (ml >= 0) {
int openflags = O_WRONLY|O_CREAT;
if (ml != 1)
openflags |= O_TRUNC;
wfd = sys_open(collected, openflags, mode);

if (wfd >= 0) {
sys_fchown(wfd, uid, gid);
sys_fchmod(wfd, mode);
Expand Down Expand Up @@ -291,6 +314,7 @@ static int __init do_copy(void)
static int __init do_symlink(void)
{
collected[N_ALIGN(name_len) + body_len] = '\0';
clean_path(collected, 0);
sys_symlink(collected + N_ALIGN(name_len), collected);
sys_lchown(collected, uid, gid);
state = SkipIt;
Expand Down

0 comments on commit 2139a7f

Please sign in to comment.