The patch titled initramfs overwrite fix has been added to the -mm tree. Its filename is initramfs-overwrite-fix.patch See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: initramfs overwrite fix From: H. Peter Anvin <hpa@xxxxxxxxx> 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@xxxxxxxxx> Cc: Michael Neuling <mikey@xxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- init/initramfs.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff -puN init/initramfs.c~initramfs-overwrite-fix init/initramfs.c --- a/init/initramfs.c~initramfs-overwrite-fix +++ a/init/initramfs.c @@ -33,6 +33,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]; @@ -44,7 +45,8 @@ static inline int hash(int major, int mi 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) { @@ -54,14 +56,17 @@ static char __init *find_link(int major, 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; @@ -232,13 +237,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) @@ -251,9 +268,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); @@ -294,6 +317,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; _ Patches currently in -mm which might be from hpa@xxxxxxxxx are origin.patch git-klibc.patch git-hdrcleanup-vs-git-klibc-on-ia64.patch git-hdrcleanup-vs-git-klibc-on-ia64-2.patch initramfs-overwrite-fix.patch initramfs-cpio-unpacking-fix.patch drivers-md-raid6algosc-fix-a-null-dereference.patch make-procfs-obligatory-except-under-config_embedded.patch make-sysctl-obligatory-except-under-config_embedded.patch initramfs-docs-update.patch md-merge-raid5-and-raid6-code.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html