diff options
| -rw-r--r-- | meta-fsl-ppc/recipes-kernel/linux/files/Fix-CVE-2014-5471_CVE-2014-5472.patch | 212 | ||||
| -rw-r--r-- | meta-fsl-ppc/recipes-kernel/linux/linux-qoriq_3.12.bb | 1 |
2 files changed, 213 insertions, 0 deletions
diff --git a/meta-fsl-ppc/recipes-kernel/linux/files/Fix-CVE-2014-5471_CVE-2014-5472.patch b/meta-fsl-ppc/recipes-kernel/linux/files/Fix-CVE-2014-5471_CVE-2014-5472.patch new file mode 100644 index 000000000..65107d63b --- /dev/null +++ b/meta-fsl-ppc/recipes-kernel/linux/files/Fix-CVE-2014-5471_CVE-2014-5472.patch | |||
| @@ -0,0 +1,212 @@ | |||
| 1 | From 4488e1f5ef40441c9846b1d0a29152c208a05e66 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Jan Kara <jack@suse.cz> | ||
| 3 | Date: Sun, 17 Aug 2014 11:49:57 +0200 | ||
| 4 | Subject: [PATCH] isofs: Fix unbounded recursion when processing relocated | ||
| 5 | directories | ||
| 6 | |||
| 7 | commit 410dd3cf4c9b36f27ed4542ee18b1af5e68645a4 upstream. | ||
| 8 | |||
| 9 | We did not check relocated directory in any way when processing Rock | ||
| 10 | Ridge 'CL' tag. Thus a corrupted isofs image can possibly have a CL | ||
| 11 | entry pointing to another CL entry leading to possibly unbounded | ||
| 12 | recursion in kernel code and thus stack overflow or deadlocks (if there | ||
| 13 | is a loop created from CL entries). | ||
| 14 | |||
| 15 | Fix the problem by not allowing CL entry to point to a directory entry | ||
| 16 | with CL entry (such use makes no good sense anyway) and by checking | ||
| 17 | whether CL entry doesn't point to itself. | ||
| 18 | |||
| 19 | Upstream status: backported (from v3.12 e4ca8b780c82c04ec0) | ||
| 20 | |||
| 21 | Reported-by: Chris Evans <cevans@google.com> | ||
| 22 | Signed-off-by: Jan Kara <jack@suse.cz> | ||
| 23 | Signed-off-by: Jiri Slaby <jslaby@suse.cz> | ||
| 24 | Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> | ||
| 25 | --- | ||
| 26 | fs/isofs/inode.c | 15 ++++++++------- | ||
| 27 | fs/isofs/isofs.h | 23 +++++++++++++++++++---- | ||
| 28 | fs/isofs/rock.c | 39 ++++++++++++++++++++++++++++----------- | ||
| 29 | 3 files changed, 55 insertions(+), 22 deletions(-) | ||
| 30 | |||
| 31 | diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c | ||
| 32 | index e5d408a..2e2af97 100644 | ||
| 33 | --- a/fs/isofs/inode.c | ||
| 34 | +++ b/fs/isofs/inode.c | ||
| 35 | @@ -61,7 +61,7 @@ static void isofs_put_super(struct super_block *sb) | ||
| 36 | return; | ||
| 37 | } | ||
| 38 | |||
| 39 | -static int isofs_read_inode(struct inode *); | ||
| 40 | +static int isofs_read_inode(struct inode *, int relocated); | ||
| 41 | static int isofs_statfs (struct dentry *, struct kstatfs *); | ||
| 42 | |||
| 43 | static struct kmem_cache *isofs_inode_cachep; | ||
| 44 | @@ -1258,7 +1258,7 @@ out_toomany: | ||
| 45 | goto out; | ||
| 46 | } | ||
| 47 | |||
| 48 | -static int isofs_read_inode(struct inode *inode) | ||
| 49 | +static int isofs_read_inode(struct inode *inode, int relocated) | ||
| 50 | { | ||
| 51 | struct super_block *sb = inode->i_sb; | ||
| 52 | struct isofs_sb_info *sbi = ISOFS_SB(sb); | ||
| 53 | @@ -1403,7 +1403,7 @@ static int isofs_read_inode(struct inode *inode) | ||
| 54 | */ | ||
| 55 | |||
| 56 | if (!high_sierra) { | ||
| 57 | - parse_rock_ridge_inode(de, inode); | ||
| 58 | + parse_rock_ridge_inode(de, inode, relocated); | ||
| 59 | /* if we want uid/gid set, override the rock ridge setting */ | ||
| 60 | if (sbi->s_uid_set) | ||
| 61 | inode->i_uid = sbi->s_uid; | ||
| 62 | @@ -1482,9 +1482,10 @@ static int isofs_iget5_set(struct inode *ino, void *data) | ||
| 63 | * offset that point to the underlying meta-data for the inode. The | ||
| 64 | * code below is otherwise similar to the iget() code in | ||
| 65 | * include/linux/fs.h */ | ||
| 66 | -struct inode *isofs_iget(struct super_block *sb, | ||
| 67 | - unsigned long block, | ||
| 68 | - unsigned long offset) | ||
| 69 | +struct inode *__isofs_iget(struct super_block *sb, | ||
| 70 | + unsigned long block, | ||
| 71 | + unsigned long offset, | ||
| 72 | + int relocated) | ||
| 73 | { | ||
| 74 | unsigned long hashval; | ||
| 75 | struct inode *inode; | ||
| 76 | @@ -1506,7 +1507,7 @@ struct inode *isofs_iget(struct super_block *sb, | ||
| 77 | return ERR_PTR(-ENOMEM); | ||
| 78 | |||
| 79 | if (inode->i_state & I_NEW) { | ||
| 80 | - ret = isofs_read_inode(inode); | ||
| 81 | + ret = isofs_read_inode(inode, relocated); | ||
| 82 | if (ret < 0) { | ||
| 83 | iget_failed(inode); | ||
| 84 | inode = ERR_PTR(ret); | ||
| 85 | diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h | ||
| 86 | index 9916723..0ac4c1f 100644 | ||
| 87 | --- a/fs/isofs/isofs.h | ||
| 88 | +++ b/fs/isofs/isofs.h | ||
| 89 | @@ -107,7 +107,7 @@ extern int iso_date(char *, int); | ||
| 90 | |||
| 91 | struct inode; /* To make gcc happy */ | ||
| 92 | |||
| 93 | -extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *); | ||
| 94 | +extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *, int relocated); | ||
| 95 | extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *); | ||
| 96 | extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *); | ||
| 97 | |||
| 98 | @@ -118,9 +118,24 @@ extern struct dentry *isofs_lookup(struct inode *, struct dentry *, unsigned int | ||
| 99 | extern struct buffer_head *isofs_bread(struct inode *, sector_t); | ||
| 100 | extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long); | ||
| 101 | |||
| 102 | -extern struct inode *isofs_iget(struct super_block *sb, | ||
| 103 | - unsigned long block, | ||
| 104 | - unsigned long offset); | ||
| 105 | +struct inode *__isofs_iget(struct super_block *sb, | ||
| 106 | + unsigned long block, | ||
| 107 | + unsigned long offset, | ||
| 108 | + int relocated); | ||
| 109 | + | ||
| 110 | +static inline struct inode *isofs_iget(struct super_block *sb, | ||
| 111 | + unsigned long block, | ||
| 112 | + unsigned long offset) | ||
| 113 | +{ | ||
| 114 | + return __isofs_iget(sb, block, offset, 0); | ||
| 115 | +} | ||
| 116 | + | ||
| 117 | +static inline struct inode *isofs_iget_reloc(struct super_block *sb, | ||
| 118 | + unsigned long block, | ||
| 119 | + unsigned long offset) | ||
| 120 | +{ | ||
| 121 | + return __isofs_iget(sb, block, offset, 1); | ||
| 122 | +} | ||
| 123 | |||
| 124 | /* Because the inode number is no longer relevant to finding the | ||
| 125 | * underlying meta-data for an inode, we are free to choose a more | ||
| 126 | diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c | ||
| 127 | index c0bf424..f488bba 100644 | ||
| 128 | --- a/fs/isofs/rock.c | ||
| 129 | +++ b/fs/isofs/rock.c | ||
| 130 | @@ -288,12 +288,16 @@ eio: | ||
| 131 | goto out; | ||
| 132 | } | ||
| 133 | |||
| 134 | +#define RR_REGARD_XA 1 | ||
| 135 | +#define RR_RELOC_DE 2 | ||
| 136 | + | ||
| 137 | static int | ||
| 138 | parse_rock_ridge_inode_internal(struct iso_directory_record *de, | ||
| 139 | - struct inode *inode, int regard_xa) | ||
| 140 | + struct inode *inode, int flags) | ||
| 141 | { | ||
| 142 | int symlink_len = 0; | ||
| 143 | int cnt, sig; | ||
| 144 | + unsigned int reloc_block; | ||
| 145 | struct inode *reloc; | ||
| 146 | struct rock_ridge *rr; | ||
| 147 | int rootflag; | ||
| 148 | @@ -305,7 +309,7 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de, | ||
| 149 | |||
| 150 | init_rock_state(&rs, inode); | ||
| 151 | setup_rock_ridge(de, inode, &rs); | ||
| 152 | - if (regard_xa) { | ||
| 153 | + if (flags & RR_REGARD_XA) { | ||
| 154 | rs.chr += 14; | ||
| 155 | rs.len -= 14; | ||
| 156 | if (rs.len < 0) | ||
| 157 | @@ -485,12 +489,22 @@ repeat: | ||
| 158 | "relocated directory\n"); | ||
| 159 | goto out; | ||
| 160 | case SIG('C', 'L'): | ||
| 161 | - ISOFS_I(inode)->i_first_extent = | ||
| 162 | - isonum_733(rr->u.CL.location); | ||
| 163 | - reloc = | ||
| 164 | - isofs_iget(inode->i_sb, | ||
| 165 | - ISOFS_I(inode)->i_first_extent, | ||
| 166 | - 0); | ||
| 167 | + if (flags & RR_RELOC_DE) { | ||
| 168 | + printk(KERN_ERR | ||
| 169 | + "ISOFS: Recursive directory relocation " | ||
| 170 | + "is not supported\n"); | ||
| 171 | + goto eio; | ||
| 172 | + } | ||
| 173 | + reloc_block = isonum_733(rr->u.CL.location); | ||
| 174 | + if (reloc_block == ISOFS_I(inode)->i_iget5_block && | ||
| 175 | + ISOFS_I(inode)->i_iget5_offset == 0) { | ||
| 176 | + printk(KERN_ERR | ||
| 177 | + "ISOFS: Directory relocation points to " | ||
| 178 | + "itself\n"); | ||
| 179 | + goto eio; | ||
| 180 | + } | ||
| 181 | + ISOFS_I(inode)->i_first_extent = reloc_block; | ||
| 182 | + reloc = isofs_iget_reloc(inode->i_sb, reloc_block, 0); | ||
| 183 | if (IS_ERR(reloc)) { | ||
| 184 | ret = PTR_ERR(reloc); | ||
| 185 | goto out; | ||
| 186 | @@ -637,9 +651,11 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit) | ||
| 187 | return rpnt; | ||
| 188 | } | ||
| 189 | |||
| 190 | -int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode) | ||
| 191 | +int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode, | ||
| 192 | + int relocated) | ||
| 193 | { | ||
| 194 | - int result = parse_rock_ridge_inode_internal(de, inode, 0); | ||
| 195 | + int flags = relocated ? RR_RELOC_DE : 0; | ||
| 196 | + int result = parse_rock_ridge_inode_internal(de, inode, flags); | ||
| 197 | |||
| 198 | /* | ||
| 199 | * if rockridge flag was reset and we didn't look for attributes | ||
| 200 | @@ -647,7 +663,8 @@ int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode) | ||
| 201 | */ | ||
| 202 | if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1) | ||
| 203 | && (ISOFS_SB(inode->i_sb)->s_rock == 2)) { | ||
| 204 | - result = parse_rock_ridge_inode_internal(de, inode, 14); | ||
| 205 | + result = parse_rock_ridge_inode_internal(de, inode, | ||
| 206 | + flags | RR_REGARD_XA); | ||
| 207 | } | ||
| 208 | return result; | ||
| 209 | } | ||
| 210 | -- | ||
| 211 | 1.9.1 | ||
| 212 | |||
diff --git a/meta-fsl-ppc/recipes-kernel/linux/linux-qoriq_3.12.bb b/meta-fsl-ppc/recipes-kernel/linux/linux-qoriq_3.12.bb index 93a0bba74..39270d481 100644 --- a/meta-fsl-ppc/recipes-kernel/linux/linux-qoriq_3.12.bb +++ b/meta-fsl-ppc/recipes-kernel/linux/linux-qoriq_3.12.bb | |||
| @@ -4,6 +4,7 @@ SRC_URI = "git://git.freescale.com/ppc/sdk/linux.git;nobranch=1 \ | |||
| 4 | file://powerpc-Fix-64-bit-builds-with-binutils-2.24.patch \ | 4 | file://powerpc-Fix-64-bit-builds-with-binutils-2.24.patch \ |
| 5 | file://Fix-for-CVE-2014-5045-fs-umount-on-symlink-leak.patch \ | 5 | file://Fix-for-CVE-2014-5045-fs-umount-on-symlink-leak.patch \ |
| 6 | file://Fix-CVE-2014-5077-sctp-inherit-auth-capable-on-INIT-collisions.patch \ | 6 | file://Fix-CVE-2014-5077-sctp-inherit-auth-capable-on-INIT-collisions.patch \ |
| 7 | file://Fix-CVE-2014-5471_CVE-2014-5472.patch \ | ||
| 7 | " | 8 | " |
| 8 | SRCREV = "c29fe1a733308cbe592b3af054a97be1b91cf2dd" | 9 | SRCREV = "c29fe1a733308cbe592b3af054a97be1b91cf2dd" |
| 9 | 10 | ||
