Skip to content

Commit 29d6849

Browse files
committed
Merge branch 'work.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull compat updates from Al Viro: "Some biarch patches - getting rid of assorted (mis)uses of compat_alloc_user_space(). Not much in that area this cycle..." * 'work.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: orangefs: simplify compat ioctl handling signalfd: lift sigmask copyin and size checks to callers of do_signalfd4() vmsplice(): lift importing iovec into vmsplice(2) and compat counterpart
2 parents a5b729e + 430ff79 commit 29d6849

File tree

3 files changed

+112
-136
lines changed

3 files changed

+112
-136
lines changed

fs/orangefs/devorangefs-req.c

Lines changed: 12 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -719,37 +719,6 @@ struct ORANGEFS_dev_map_desc32 {
719719
__s32 count;
720720
};
721721

722-
static unsigned long translate_dev_map26(unsigned long args, long *error)
723-
{
724-
struct ORANGEFS_dev_map_desc32 __user *p32 = (void __user *)args;
725-
/*
726-
* Depending on the architecture, allocate some space on the
727-
* user-call-stack based on our expected layout.
728-
*/
729-
struct ORANGEFS_dev_map_desc __user *p =
730-
compat_alloc_user_space(sizeof(*p));
731-
compat_uptr_t addr;
732-
733-
*error = 0;
734-
/* get the ptr from the 32 bit user-space */
735-
if (get_user(addr, &p32->ptr))
736-
goto err;
737-
/* try to put that into a 64-bit layout */
738-
if (put_user(compat_ptr(addr), &p->ptr))
739-
goto err;
740-
/* copy the remaining fields */
741-
if (copy_in_user(&p->total_size, &p32->total_size, sizeof(__s32)))
742-
goto err;
743-
if (copy_in_user(&p->size, &p32->size, sizeof(__s32)))
744-
goto err;
745-
if (copy_in_user(&p->count, &p32->count, sizeof(__s32)))
746-
goto err;
747-
return (unsigned long)p;
748-
err:
749-
*error = -EFAULT;
750-
return 0;
751-
}
752-
753722
/*
754723
* 32 bit user-space apps' ioctl handlers when kernel modules
755724
* is compiled as a 64 bit one
@@ -758,25 +727,26 @@ static long orangefs_devreq_compat_ioctl(struct file *filp, unsigned int cmd,
758727
unsigned long args)
759728
{
760729
long ret;
761-
unsigned long arg = args;
762730

763731
/* Check for properly constructed commands */
764732
ret = check_ioctl_command(cmd);
765733
if (ret < 0)
766734
return ret;
767735
if (cmd == ORANGEFS_DEV_MAP) {
768-
/*
769-
* convert the arguments to what we expect internally
770-
* in kernel space
771-
*/
772-
arg = translate_dev_map26(args, &ret);
773-
if (ret < 0) {
774-
gossip_err("Could not translate dev map\n");
775-
return ret;
776-
}
736+
struct ORANGEFS_dev_map_desc desc;
737+
struct ORANGEFS_dev_map_desc32 d32;
738+
739+
if (copy_from_user(&d32, (void __user *)args, sizeof(d32)))
740+
return -EFAULT;
741+
742+
desc.ptr = compat_ptr(d32.ptr);
743+
desc.total_size = d32.total_size;
744+
desc.size = d32.size;
745+
desc.count = d32.count;
746+
return orangefs_bufmap_initialize(&desc);
777747
}
778748
/* no other ioctl requires translation */
779-
return dispatch_ioctl_command(cmd, arg);
749+
return dispatch_ioctl_command(cmd, args);
780750
}
781751

782752
#endif /* CONFIG_COMPAT is in .config */

fs/signalfd.c

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,8 @@ static const struct file_operations signalfd_fops = {
259259
.llseek = noop_llseek,
260260
};
261261

262-
static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
263-
int flags)
262+
static int do_signalfd4(int ufd, sigset_t *mask, int flags)
264263
{
265-
sigset_t sigmask;
266264
struct signalfd_ctx *ctx;
267265

268266
/* Check the SFD_* constants for consistency. */
@@ -272,18 +270,15 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
272270
if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK))
273271
return -EINVAL;
274272

275-
if (sizemask != sizeof(sigset_t) ||
276-
copy_from_user(&sigmask, user_mask, sizeof(sigmask)))
277-
return -EINVAL;
278-
sigdelsetmask(&sigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
279-
signotset(&sigmask);
273+
sigdelsetmask(mask, sigmask(SIGKILL) | sigmask(SIGSTOP));
274+
signotset(mask);
280275

281276
if (ufd == -1) {
282277
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
283278
if (!ctx)
284279
return -ENOMEM;
285280

286-
ctx->sigmask = sigmask;
281+
ctx->sigmask = *mask;
287282

288283
/*
289284
* When we call this, the initialization must be complete, since
@@ -303,7 +298,7 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
303298
return -EINVAL;
304299
}
305300
spin_lock_irq(&current->sighand->siglock);
306-
ctx->sigmask = sigmask;
301+
ctx->sigmask = *mask;
307302
spin_unlock_irq(&current->sighand->siglock);
308303

309304
wake_up(&current->sighand->signalfd_wqh);
@@ -316,46 +311,51 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
316311
SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask,
317312
size_t, sizemask, int, flags)
318313
{
319-
return do_signalfd4(ufd, user_mask, sizemask, flags);
314+
sigset_t mask;
315+
316+
if (sizemask != sizeof(sigset_t) ||
317+
copy_from_user(&mask, user_mask, sizeof(mask)))
318+
return -EINVAL;
319+
return do_signalfd4(ufd, &mask, flags);
320320
}
321321

322322
SYSCALL_DEFINE3(signalfd, int, ufd, sigset_t __user *, user_mask,
323323
size_t, sizemask)
324324
{
325-
return do_signalfd4(ufd, user_mask, sizemask, 0);
325+
sigset_t mask;
326+
327+
if (sizemask != sizeof(sigset_t) ||
328+
copy_from_user(&mask, user_mask, sizeof(mask)))
329+
return -EINVAL;
330+
return do_signalfd4(ufd, &mask, 0);
326331
}
327332

328333
#ifdef CONFIG_COMPAT
329334
static long do_compat_signalfd4(int ufd,
330-
const compat_sigset_t __user *sigmask,
335+
const compat_sigset_t __user *user_mask,
331336
compat_size_t sigsetsize, int flags)
332337
{
333-
sigset_t tmp;
334-
sigset_t __user *ksigmask;
338+
sigset_t mask;
335339

336340
if (sigsetsize != sizeof(compat_sigset_t))
337341
return -EINVAL;
338-
if (get_compat_sigset(&tmp, sigmask))
339-
return -EFAULT;
340-
ksigmask = compat_alloc_user_space(sizeof(sigset_t));
341-
if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
342+
if (get_compat_sigset(&mask, user_mask))
342343
return -EFAULT;
343-
344-
return do_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags);
344+
return do_signalfd4(ufd, &mask, flags);
345345
}
346346

347347
COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd,
348-
const compat_sigset_t __user *, sigmask,
348+
const compat_sigset_t __user *, user_mask,
349349
compat_size_t, sigsetsize,
350350
int, flags)
351351
{
352-
return do_compat_signalfd4(ufd, sigmask, sigsetsize, flags);
352+
return do_compat_signalfd4(ufd, user_mask, sigsetsize, flags);
353353
}
354354

355355
COMPAT_SYSCALL_DEFINE3(signalfd, int, ufd,
356-
const compat_sigset_t __user *,sigmask,
356+
const compat_sigset_t __user *, user_mask,
357357
compat_size_t, sigsetsize)
358358
{
359-
return do_compat_signalfd4(ufd, sigmask, sigsetsize, 0);
359+
return do_compat_signalfd4(ufd, user_mask, sigsetsize, 0);
360360
}
361361
#endif

fs/splice.c

Lines changed: 75 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,38 +1243,26 @@ static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
12431243
* For lack of a better implementation, implement vmsplice() to userspace
12441244
* as a simple copy of the pipes pages to the user iov.
12451245
*/
1246-
static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
1247-
unsigned long nr_segs, unsigned int flags)
1246+
static long vmsplice_to_user(struct file *file, struct iov_iter *iter,
1247+
unsigned int flags)
12481248
{
1249-
struct pipe_inode_info *pipe;
1250-
struct splice_desc sd;
1251-
long ret;
1252-
struct iovec iovstack[UIO_FASTIOV];
1253-
struct iovec *iov = iovstack;
1254-
struct iov_iter iter;
1249+
struct pipe_inode_info *pipe = get_pipe_info(file);
1250+
struct splice_desc sd = {
1251+
.total_len = iov_iter_count(iter),
1252+
.flags = flags,
1253+
.u.data = iter
1254+
};
1255+
long ret = 0;
12551256

1256-
pipe = get_pipe_info(file);
12571257
if (!pipe)
12581258
return -EBADF;
12591259

1260-
ret = import_iovec(READ, uiov, nr_segs,
1261-
ARRAY_SIZE(iovstack), &iov, &iter);
1262-
if (ret < 0)
1263-
return ret;
1264-
1265-
sd.total_len = iov_iter_count(&iter);
1266-
sd.len = 0;
1267-
sd.flags = flags;
1268-
sd.u.data = &iter;
1269-
sd.pos = 0;
1270-
12711260
if (sd.total_len) {
12721261
pipe_lock(pipe);
12731262
ret = __splice_from_pipe(pipe, &sd, pipe_to_user);
12741263
pipe_unlock(pipe);
12751264
}
12761265

1277-
kfree(iov);
12781266
return ret;
12791267
}
12801268

@@ -1283,14 +1271,11 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
12831271
* as splice-from-memory, where the regular splice is splice-from-file (or
12841272
* to file). In both cases the output is a pipe, naturally.
12851273
*/
1286-
static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov,
1287-
unsigned long nr_segs, unsigned int flags)
1274+
static long vmsplice_to_pipe(struct file *file, struct iov_iter *iter,
1275+
unsigned int flags)
12881276
{
12891277
struct pipe_inode_info *pipe;
1290-
struct iovec iovstack[UIO_FASTIOV];
1291-
struct iovec *iov = iovstack;
1292-
struct iov_iter from;
1293-
long ret;
1278+
long ret = 0;
12941279
unsigned buf_flag = 0;
12951280

12961281
if (flags & SPLICE_F_GIFT)
@@ -1300,22 +1285,31 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov,
13001285
if (!pipe)
13011286
return -EBADF;
13021287

1303-
ret = import_iovec(WRITE, uiov, nr_segs,
1304-
ARRAY_SIZE(iovstack), &iov, &from);
1305-
if (ret < 0)
1306-
return ret;
1307-
13081288
pipe_lock(pipe);
13091289
ret = wait_for_space(pipe, flags);
13101290
if (!ret)
1311-
ret = iter_to_pipe(&from, pipe, buf_flag);
1291+
ret = iter_to_pipe(iter, pipe, buf_flag);
13121292
pipe_unlock(pipe);
13131293
if (ret > 0)
13141294
wakeup_pipe_readers(pipe);
1315-
kfree(iov);
13161295
return ret;
13171296
}
13181297

1298+
static int vmsplice_type(struct fd f, int *type)
1299+
{
1300+
if (!f.file)
1301+
return -EBADF;
1302+
if (f.file->f_mode & FMODE_WRITE) {
1303+
*type = WRITE;
1304+
} else if (f.file->f_mode & FMODE_READ) {
1305+
*type = READ;
1306+
} else {
1307+
fdput(f);
1308+
return -EBADF;
1309+
}
1310+
return 0;
1311+
}
1312+
13191313
/*
13201314
* Note that vmsplice only really supports true splicing _from_ user memory
13211315
* to a pipe, not the other way around. Splicing from user memory is a simple
@@ -1332,57 +1326,69 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov,
13321326
* Currently we punt and implement it as a normal copy, see pipe_to_user().
13331327
*
13341328
*/
1335-
static long do_vmsplice(int fd, const struct iovec __user *iov,
1336-
unsigned long nr_segs, unsigned int flags)
1329+
static long do_vmsplice(struct file *f, struct iov_iter *iter, unsigned int flags)
13371330
{
1338-
struct fd f;
1339-
long error;
1340-
13411331
if (unlikely(flags & ~SPLICE_F_ALL))
13421332
return -EINVAL;
1343-
if (unlikely(nr_segs > UIO_MAXIOV))
1344-
return -EINVAL;
1345-
else if (unlikely(!nr_segs))
1346-
return 0;
13471333

1348-
error = -EBADF;
1349-
f = fdget(fd);
1350-
if (f.file) {
1351-
if (f.file->f_mode & FMODE_WRITE)
1352-
error = vmsplice_to_pipe(f.file, iov, nr_segs, flags);
1353-
else if (f.file->f_mode & FMODE_READ)
1354-
error = vmsplice_to_user(f.file, iov, nr_segs, flags);
1355-
1356-
fdput(f);
1357-
}
1334+
if (!iov_iter_count(iter))
1335+
return 0;
13581336

1359-
return error;
1337+
if (iov_iter_rw(iter) == WRITE)
1338+
return vmsplice_to_pipe(f, iter, flags);
1339+
else
1340+
return vmsplice_to_user(f, iter, flags);
13601341
}
13611342

1362-
SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, iov,
1343+
SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov,
13631344
unsigned long, nr_segs, unsigned int, flags)
13641345
{
1365-
return do_vmsplice(fd, iov, nr_segs, flags);
1346+
struct iovec iovstack[UIO_FASTIOV];
1347+
struct iovec *iov = iovstack;
1348+
struct iov_iter iter;
1349+
long error;
1350+
struct fd f;
1351+
int type;
1352+
1353+
f = fdget(fd);
1354+
error = vmsplice_type(f, &type);
1355+
if (error)
1356+
return error;
1357+
1358+
error = import_iovec(type, uiov, nr_segs,
1359+
ARRAY_SIZE(iovstack), &iov, &iter);
1360+
if (!error) {
1361+
error = do_vmsplice(f.file, &iter, flags);
1362+
kfree(iov);
1363+
}
1364+
fdput(f);
1365+
return error;
13661366
}
13671367

13681368
#ifdef CONFIG_COMPAT
13691369
COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, iov32,
13701370
unsigned int, nr_segs, unsigned int, flags)
13711371
{
1372-
unsigned i;
1373-
struct iovec __user *iov;
1374-
if (nr_segs > UIO_MAXIOV)
1375-
return -EINVAL;
1376-
iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
1377-
for (i = 0; i < nr_segs; i++) {
1378-
struct compat_iovec v;
1379-
if (get_user(v.iov_base, &iov32[i].iov_base) ||
1380-
get_user(v.iov_len, &iov32[i].iov_len) ||
1381-
put_user(compat_ptr(v.iov_base), &iov[i].iov_base) ||
1382-
put_user(v.iov_len, &iov[i].iov_len))
1383-
return -EFAULT;
1372+
struct iovec iovstack[UIO_FASTIOV];
1373+
struct iovec *iov = iovstack;
1374+
struct iov_iter iter;
1375+
long error;
1376+
struct fd f;
1377+
int type;
1378+
1379+
f = fdget(fd);
1380+
error = vmsplice_type(f, &type);
1381+
if (error)
1382+
return error;
1383+
1384+
error = compat_import_iovec(type, iov32, nr_segs,
1385+
ARRAY_SIZE(iovstack), &iov, &iter);
1386+
if (!error) {
1387+
error = do_vmsplice(f.file, &iter, flags);
1388+
kfree(iov);
13841389
}
1385-
return do_vmsplice(fd, iov, nr_segs, flags);
1390+
fdput(f);
1391+
return error;
13861392
}
13871393
#endif
13881394

0 commit comments

Comments
 (0)