diff options
author | James Morris <jmorris@namei.org> | 2009-05-08 03:56:47 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-05-08 03:56:47 -0400 |
commit | d254117099d711f215e62427f55dfb8ebd5ad011 (patch) | |
tree | 0848ff8dd74314fec14a86497f8d288c86ba7c65 /fs/compat.c | |
parent | 07ff7a0b187f3951788f64ae1f30e8109bc8e9eb (diff) | |
parent | 8c9ed899b44c19e81859fbb0e9d659fe2f8630fc (diff) |
Merge branch 'master' into next
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 141 |
1 files changed, 103 insertions, 38 deletions
diff --git a/fs/compat.c b/fs/compat.c index 55efdfebdf5a..681ed81e6be0 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/poll.h> | 51 | #include <linux/poll.h> |
52 | #include <linux/mm.h> | 52 | #include <linux/mm.h> |
53 | #include <linux/eventpoll.h> | 53 | #include <linux/eventpoll.h> |
54 | #include <linux/fs_struct.h> | ||
54 | 55 | ||
55 | #include <asm/uaccess.h> | 56 | #include <asm/uaccess.h> |
56 | #include <asm/mmu_context.h> | 57 | #include <asm/mmu_context.h> |
@@ -180,22 +181,24 @@ asmlinkage long compat_sys_newstat(char __user * filename, | |||
180 | struct compat_stat __user *statbuf) | 181 | struct compat_stat __user *statbuf) |
181 | { | 182 | { |
182 | struct kstat stat; | 183 | struct kstat stat; |
183 | int error = vfs_stat_fd(AT_FDCWD, filename, &stat); | 184 | int error; |
184 | 185 | ||
185 | if (!error) | 186 | error = vfs_stat(filename, &stat); |
186 | error = cp_compat_stat(&stat, statbuf); | 187 | if (error) |
187 | return error; | 188 | return error; |
189 | return cp_compat_stat(&stat, statbuf); | ||
188 | } | 190 | } |
189 | 191 | ||
190 | asmlinkage long compat_sys_newlstat(char __user * filename, | 192 | asmlinkage long compat_sys_newlstat(char __user * filename, |
191 | struct compat_stat __user *statbuf) | 193 | struct compat_stat __user *statbuf) |
192 | { | 194 | { |
193 | struct kstat stat; | 195 | struct kstat stat; |
194 | int error = vfs_lstat_fd(AT_FDCWD, filename, &stat); | 196 | int error; |
195 | 197 | ||
196 | if (!error) | 198 | error = vfs_lstat(filename, &stat); |
197 | error = cp_compat_stat(&stat, statbuf); | 199 | if (error) |
198 | return error; | 200 | return error; |
201 | return cp_compat_stat(&stat, statbuf); | ||
199 | } | 202 | } |
200 | 203 | ||
201 | #ifndef __ARCH_WANT_STAT64 | 204 | #ifndef __ARCH_WANT_STAT64 |
@@ -203,21 +206,12 @@ asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user *filename, | |||
203 | struct compat_stat __user *statbuf, int flag) | 206 | struct compat_stat __user *statbuf, int flag) |
204 | { | 207 | { |
205 | struct kstat stat; | 208 | struct kstat stat; |
206 | int error = -EINVAL; | 209 | int error; |
207 | |||
208 | if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) | ||
209 | goto out; | ||
210 | |||
211 | if (flag & AT_SYMLINK_NOFOLLOW) | ||
212 | error = vfs_lstat_fd(dfd, filename, &stat); | ||
213 | else | ||
214 | error = vfs_stat_fd(dfd, filename, &stat); | ||
215 | |||
216 | if (!error) | ||
217 | error = cp_compat_stat(&stat, statbuf); | ||
218 | 210 | ||
219 | out: | 211 | error = vfs_fstatat(dfd, filename, &stat, flag); |
220 | return error; | 212 | if (error) |
213 | return error; | ||
214 | return cp_compat_stat(&stat, statbuf); | ||
221 | } | 215 | } |
222 | #endif | 216 | #endif |
223 | 217 | ||
@@ -1195,16 +1189,12 @@ out: | |||
1195 | return ret; | 1189 | return ret; |
1196 | } | 1190 | } |
1197 | 1191 | ||
1198 | asmlinkage ssize_t | 1192 | static size_t compat_readv(struct file *file, |
1199 | compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen) | 1193 | const struct compat_iovec __user *vec, |
1194 | unsigned long vlen, loff_t *pos) | ||
1200 | { | 1195 | { |
1201 | struct file *file; | ||
1202 | ssize_t ret = -EBADF; | 1196 | ssize_t ret = -EBADF; |
1203 | 1197 | ||
1204 | file = fget(fd); | ||
1205 | if (!file) | ||
1206 | return -EBADF; | ||
1207 | |||
1208 | if (!(file->f_mode & FMODE_READ)) | 1198 | if (!(file->f_mode & FMODE_READ)) |
1209 | goto out; | 1199 | goto out; |
1210 | 1200 | ||
@@ -1212,25 +1202,56 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsign | |||
1212 | if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read)) | 1202 | if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read)) |
1213 | goto out; | 1203 | goto out; |
1214 | 1204 | ||
1215 | ret = compat_do_readv_writev(READ, file, vec, vlen, &file->f_pos); | 1205 | ret = compat_do_readv_writev(READ, file, vec, vlen, pos); |
1216 | 1206 | ||
1217 | out: | 1207 | out: |
1218 | if (ret > 0) | 1208 | if (ret > 0) |
1219 | add_rchar(current, ret); | 1209 | add_rchar(current, ret); |
1220 | inc_syscr(current); | 1210 | inc_syscr(current); |
1221 | fput(file); | ||
1222 | return ret; | 1211 | return ret; |
1223 | } | 1212 | } |
1224 | 1213 | ||
1225 | asmlinkage ssize_t | 1214 | asmlinkage ssize_t |
1226 | compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen) | 1215 | compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, |
1216 | unsigned long vlen) | ||
1227 | { | 1217 | { |
1228 | struct file *file; | 1218 | struct file *file; |
1229 | ssize_t ret = -EBADF; | 1219 | int fput_needed; |
1220 | ssize_t ret; | ||
1230 | 1221 | ||
1231 | file = fget(fd); | 1222 | file = fget_light(fd, &fput_needed); |
1223 | if (!file) | ||
1224 | return -EBADF; | ||
1225 | ret = compat_readv(file, vec, vlen, &file->f_pos); | ||
1226 | fput_light(file, fput_needed); | ||
1227 | return ret; | ||
1228 | } | ||
1229 | |||
1230 | asmlinkage ssize_t | ||
1231 | compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec, | ||
1232 | unsigned long vlen, u32 pos_low, u32 pos_high) | ||
1233 | { | ||
1234 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | ||
1235 | struct file *file; | ||
1236 | int fput_needed; | ||
1237 | ssize_t ret; | ||
1238 | |||
1239 | if (pos < 0) | ||
1240 | return -EINVAL; | ||
1241 | file = fget_light(fd, &fput_needed); | ||
1232 | if (!file) | 1242 | if (!file) |
1233 | return -EBADF; | 1243 | return -EBADF; |
1244 | ret = compat_readv(file, vec, vlen, &pos); | ||
1245 | fput_light(file, fput_needed); | ||
1246 | return ret; | ||
1247 | } | ||
1248 | |||
1249 | static size_t compat_writev(struct file *file, | ||
1250 | const struct compat_iovec __user *vec, | ||
1251 | unsigned long vlen, loff_t *pos) | ||
1252 | { | ||
1253 | ssize_t ret = -EBADF; | ||
1254 | |||
1234 | if (!(file->f_mode & FMODE_WRITE)) | 1255 | if (!(file->f_mode & FMODE_WRITE)) |
1235 | goto out; | 1256 | goto out; |
1236 | 1257 | ||
@@ -1238,13 +1259,47 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsig | |||
1238 | if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write)) | 1259 | if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write)) |
1239 | goto out; | 1260 | goto out; |
1240 | 1261 | ||
1241 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, &file->f_pos); | 1262 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos); |
1242 | 1263 | ||
1243 | out: | 1264 | out: |
1244 | if (ret > 0) | 1265 | if (ret > 0) |
1245 | add_wchar(current, ret); | 1266 | add_wchar(current, ret); |
1246 | inc_syscw(current); | 1267 | inc_syscw(current); |
1247 | fput(file); | 1268 | return ret; |
1269 | } | ||
1270 | |||
1271 | asmlinkage ssize_t | ||
1272 | compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, | ||
1273 | unsigned long vlen) | ||
1274 | { | ||
1275 | struct file *file; | ||
1276 | int fput_needed; | ||
1277 | ssize_t ret; | ||
1278 | |||
1279 | file = fget_light(fd, &fput_needed); | ||
1280 | if (!file) | ||
1281 | return -EBADF; | ||
1282 | ret = compat_writev(file, vec, vlen, &file->f_pos); | ||
1283 | fput_light(file, fput_needed); | ||
1284 | return ret; | ||
1285 | } | ||
1286 | |||
1287 | asmlinkage ssize_t | ||
1288 | compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec, | ||
1289 | unsigned long vlen, u32 pos_low, u32 pos_high) | ||
1290 | { | ||
1291 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | ||
1292 | struct file *file; | ||
1293 | int fput_needed; | ||
1294 | ssize_t ret; | ||
1295 | |||
1296 | if (pos < 0) | ||
1297 | return -EINVAL; | ||
1298 | file = fget_light(fd, &fput_needed); | ||
1299 | if (!file) | ||
1300 | return -EBADF; | ||
1301 | ret = compat_writev(file, vec, vlen, &pos); | ||
1302 | fput_light(file, fput_needed); | ||
1248 | return ret; | 1303 | return ret; |
1249 | } | 1304 | } |
1250 | 1305 | ||
@@ -1421,6 +1476,7 @@ int compat_do_execve(char * filename, | |||
1421 | struct linux_binprm *bprm; | 1476 | struct linux_binprm *bprm; |
1422 | struct file *file; | 1477 | struct file *file; |
1423 | struct files_struct *displaced; | 1478 | struct files_struct *displaced; |
1479 | bool clear_in_exec; | ||
1424 | int retval; | 1480 | int retval; |
1425 | 1481 | ||
1426 | retval = unshare_files(&displaced); | 1482 | retval = unshare_files(&displaced); |
@@ -1441,12 +1497,16 @@ int compat_do_execve(char * filename, | |||
1441 | bprm->cred = prepare_exec_creds(); | 1497 | bprm->cred = prepare_exec_creds(); |
1442 | if (!bprm->cred) | 1498 | if (!bprm->cred) |
1443 | goto out_unlock; | 1499 | goto out_unlock; |
1444 | check_unsafe_exec(bprm); | 1500 | |
1501 | retval = check_unsafe_exec(bprm); | ||
1502 | if (retval < 0) | ||
1503 | goto out_unlock; | ||
1504 | clear_in_exec = retval; | ||
1445 | 1505 | ||
1446 | file = open_exec(filename); | 1506 | file = open_exec(filename); |
1447 | retval = PTR_ERR(file); | 1507 | retval = PTR_ERR(file); |
1448 | if (IS_ERR(file)) | 1508 | if (IS_ERR(file)) |
1449 | goto out_unlock; | 1509 | goto out_unmark; |
1450 | 1510 | ||
1451 | sched_exec(); | 1511 | sched_exec(); |
1452 | 1512 | ||
@@ -1488,6 +1548,7 @@ int compat_do_execve(char * filename, | |||
1488 | goto out; | 1548 | goto out; |
1489 | 1549 | ||
1490 | /* execve succeeded */ | 1550 | /* execve succeeded */ |
1551 | current->fs->in_exec = 0; | ||
1491 | current->in_execve = 0; | 1552 | current->in_execve = 0; |
1492 | mutex_unlock(¤t->cred_exec_mutex); | 1553 | mutex_unlock(¤t->cred_exec_mutex); |
1493 | acct_update_integrals(current); | 1554 | acct_update_integrals(current); |
@@ -1506,6 +1567,10 @@ out_file: | |||
1506 | fput(bprm->file); | 1567 | fput(bprm->file); |
1507 | } | 1568 | } |
1508 | 1569 | ||
1570 | out_unmark: | ||
1571 | if (clear_in_exec) | ||
1572 | current->fs->in_exec = 0; | ||
1573 | |||
1509 | out_unlock: | 1574 | out_unlock: |
1510 | current->in_execve = 0; | 1575 | current->in_execve = 0; |
1511 | mutex_unlock(¤t->cred_exec_mutex); | 1576 | mutex_unlock(¤t->cred_exec_mutex); |