aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2009-05-08 03:56:47 -0400
committerJames Morris <jmorris@namei.org>2009-05-08 03:56:47 -0400
commitd254117099d711f215e62427f55dfb8ebd5ad011 (patch)
tree0848ff8dd74314fec14a86497f8d288c86ba7c65 /fs/compat.c
parent07ff7a0b187f3951788f64ae1f30e8109bc8e9eb (diff)
parent8c9ed899b44c19e81859fbb0e9d659fe2f8630fc (diff)
Merge branch 'master' into next
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c141
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
190asmlinkage long compat_sys_newlstat(char __user * filename, 192asmlinkage 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
219out: 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
1198asmlinkage ssize_t 1192static size_t compat_readv(struct file *file,
1199compat_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
1217out: 1207out:
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
1225asmlinkage ssize_t 1214asmlinkage ssize_t
1226compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen) 1215compat_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
1230asmlinkage ssize_t
1231compat_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
1249static 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
1243out: 1264out:
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
1271asmlinkage ssize_t
1272compat_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
1287asmlinkage ssize_t
1288compat_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(&current->cred_exec_mutex); 1553 mutex_unlock(&current->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
1570out_unmark:
1571 if (clear_in_exec)
1572 current->fs->in_exec = 0;
1573
1509out_unlock: 1574out_unlock:
1510 current->in_execve = 0; 1575 current->in_execve = 0;
1511 mutex_unlock(&current->cred_exec_mutex); 1576 mutex_unlock(&current->cred_exec_mutex);