diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-02-06 12:45:27 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-03-20 21:29:32 -0400 |
commit | 8de52778798fe39660a8d6b26f290e0c93202761 (patch) | |
tree | 56384beb7863c1f338f2b66b509bf58eea5a99c2 /fs/minix | |
parent | c16fa4f2ad19908a47c63d8fa436a1178438c7e7 (diff) |
vfs: check i_nlink limits in vfs_{mkdir,rename_dir,link}
New field of struct super_block - ->s_max_links. Maximal allowed
value of ->i_nlink or 0; in the latter case all checks still need
to be done in ->link/->mkdir/->rename instances. Note that this
limit applies both to directoris and to non-directories.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/minix')
-rw-r--r-- | fs/minix/inode.c | 10 | ||||
-rw-r--r-- | fs/minix/minix.h | 1 | ||||
-rw-r--r-- | fs/minix/namei.c | 14 |
3 files changed, 6 insertions, 19 deletions
diff --git a/fs/minix/inode.c b/fs/minix/inode.c index fa8b612b8ce2..62c697caffb9 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c | |||
@@ -190,24 +190,24 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) | |||
190 | sbi->s_version = MINIX_V1; | 190 | sbi->s_version = MINIX_V1; |
191 | sbi->s_dirsize = 16; | 191 | sbi->s_dirsize = 16; |
192 | sbi->s_namelen = 14; | 192 | sbi->s_namelen = 14; |
193 | sbi->s_link_max = MINIX_LINK_MAX; | 193 | s->s_max_links = MINIX_LINK_MAX; |
194 | } else if (s->s_magic == MINIX_SUPER_MAGIC2) { | 194 | } else if (s->s_magic == MINIX_SUPER_MAGIC2) { |
195 | sbi->s_version = MINIX_V1; | 195 | sbi->s_version = MINIX_V1; |
196 | sbi->s_dirsize = 32; | 196 | sbi->s_dirsize = 32; |
197 | sbi->s_namelen = 30; | 197 | sbi->s_namelen = 30; |
198 | sbi->s_link_max = MINIX_LINK_MAX; | 198 | s->s_max_links = MINIX_LINK_MAX; |
199 | } else if (s->s_magic == MINIX2_SUPER_MAGIC) { | 199 | } else if (s->s_magic == MINIX2_SUPER_MAGIC) { |
200 | sbi->s_version = MINIX_V2; | 200 | sbi->s_version = MINIX_V2; |
201 | sbi->s_nzones = ms->s_zones; | 201 | sbi->s_nzones = ms->s_zones; |
202 | sbi->s_dirsize = 16; | 202 | sbi->s_dirsize = 16; |
203 | sbi->s_namelen = 14; | 203 | sbi->s_namelen = 14; |
204 | sbi->s_link_max = MINIX2_LINK_MAX; | 204 | s->s_max_links = MINIX2_LINK_MAX; |
205 | } else if (s->s_magic == MINIX2_SUPER_MAGIC2) { | 205 | } else if (s->s_magic == MINIX2_SUPER_MAGIC2) { |
206 | sbi->s_version = MINIX_V2; | 206 | sbi->s_version = MINIX_V2; |
207 | sbi->s_nzones = ms->s_zones; | 207 | sbi->s_nzones = ms->s_zones; |
208 | sbi->s_dirsize = 32; | 208 | sbi->s_dirsize = 32; |
209 | sbi->s_namelen = 30; | 209 | sbi->s_namelen = 30; |
210 | sbi->s_link_max = MINIX2_LINK_MAX; | 210 | s->s_max_links = MINIX2_LINK_MAX; |
211 | } else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) { | 211 | } else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) { |
212 | m3s = (struct minix3_super_block *) bh->b_data; | 212 | m3s = (struct minix3_super_block *) bh->b_data; |
213 | s->s_magic = m3s->s_magic; | 213 | s->s_magic = m3s->s_magic; |
@@ -221,9 +221,9 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) | |||
221 | sbi->s_dirsize = 64; | 221 | sbi->s_dirsize = 64; |
222 | sbi->s_namelen = 60; | 222 | sbi->s_namelen = 60; |
223 | sbi->s_version = MINIX_V3; | 223 | sbi->s_version = MINIX_V3; |
224 | sbi->s_link_max = MINIX2_LINK_MAX; | ||
225 | sbi->s_mount_state = MINIX_VALID_FS; | 224 | sbi->s_mount_state = MINIX_VALID_FS; |
226 | sb_set_blocksize(s, m3s->s_blocksize); | 225 | sb_set_blocksize(s, m3s->s_blocksize); |
226 | s->s_max_links = MINIX2_LINK_MAX; | ||
227 | } else | 227 | } else |
228 | goto out_no_fs; | 228 | goto out_no_fs; |
229 | 229 | ||
diff --git a/fs/minix/minix.h b/fs/minix/minix.h index c889ef0aa571..1ebd11854622 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h | |||
@@ -34,7 +34,6 @@ struct minix_sb_info { | |||
34 | unsigned long s_max_size; | 34 | unsigned long s_max_size; |
35 | int s_dirsize; | 35 | int s_dirsize; |
36 | int s_namelen; | 36 | int s_namelen; |
37 | int s_link_max; | ||
38 | struct buffer_head ** s_imap; | 37 | struct buffer_head ** s_imap; |
39 | struct buffer_head ** s_zmap; | 38 | struct buffer_head ** s_zmap; |
40 | struct buffer_head * s_sbh; | 39 | struct buffer_head * s_sbh; |
diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 2f76e38c2065..2d0ee1786305 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c | |||
@@ -94,9 +94,6 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir, | |||
94 | { | 94 | { |
95 | struct inode *inode = old_dentry->d_inode; | 95 | struct inode *inode = old_dentry->d_inode; |
96 | 96 | ||
97 | if (inode->i_nlink >= minix_sb(inode->i_sb)->s_link_max) | ||
98 | return -EMLINK; | ||
99 | |||
100 | inode->i_ctime = CURRENT_TIME_SEC; | 97 | inode->i_ctime = CURRENT_TIME_SEC; |
101 | inode_inc_link_count(inode); | 98 | inode_inc_link_count(inode); |
102 | ihold(inode); | 99 | ihold(inode); |
@@ -106,10 +103,7 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir, | |||
106 | static int minix_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode) | 103 | static int minix_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode) |
107 | { | 104 | { |
108 | struct inode * inode; | 105 | struct inode * inode; |
109 | int err = -EMLINK; | 106 | int err; |
110 | |||
111 | if (dir->i_nlink >= minix_sb(dir->i_sb)->s_link_max) | ||
112 | goto out; | ||
113 | 107 | ||
114 | inode_inc_link_count(dir); | 108 | inode_inc_link_count(dir); |
115 | 109 | ||
@@ -181,7 +175,6 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry) | |||
181 | static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, | 175 | static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, |
182 | struct inode * new_dir, struct dentry *new_dentry) | 176 | struct inode * new_dir, struct dentry *new_dentry) |
183 | { | 177 | { |
184 | struct minix_sb_info * info = minix_sb(old_dir->i_sb); | ||
185 | struct inode * old_inode = old_dentry->d_inode; | 178 | struct inode * old_inode = old_dentry->d_inode; |
186 | struct inode * new_inode = new_dentry->d_inode; | 179 | struct inode * new_inode = new_dentry->d_inode; |
187 | struct page * dir_page = NULL; | 180 | struct page * dir_page = NULL; |
@@ -219,11 +212,6 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
219 | drop_nlink(new_inode); | 212 | drop_nlink(new_inode); |
220 | inode_dec_link_count(new_inode); | 213 | inode_dec_link_count(new_inode); |
221 | } else { | 214 | } else { |
222 | if (dir_de) { | ||
223 | err = -EMLINK; | ||
224 | if (new_dir->i_nlink >= info->s_link_max) | ||
225 | goto out_dir; | ||
226 | } | ||
227 | err = minix_add_link(new_dentry, old_inode); | 215 | err = minix_add_link(new_dentry, old_inode); |
228 | if (err) | 216 | if (err) |
229 | goto out_dir; | 217 | goto out_dir; |