git.samba.org
/
sfrench
/
cifs-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
[sfrench/cifs-2.6.git]
/
fs
/
splice.c
diff --git
a/fs/splice.c
b/fs/splice.c
index 59a941d404d9c60b46a83ced4472ee915a7fe93c..14e2262c0a046641ece8086c7f7329a8a114ebda 100644
(file)
--- a/
fs/splice.c
+++ b/
fs/splice.c
@@
-254,11
+254,16
@@
ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
}
while (page_nr < spd_pages)
}
while (page_nr < spd_pages)
-
page_cache_release(spd->pages[page_nr++]
);
+
spd->spd_release(spd, page_nr++
);
return ret;
}
return ret;
}
+static void spd_release_page(struct splice_pipe_desc *spd, unsigned int i)
+{
+ page_cache_release(spd->pages[i]);
+}
+
static int
__generic_file_splice_read(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
static int
__generic_file_splice_read(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
@@
-277,6
+282,7
@@
__generic_file_splice_read(struct file *in, loff_t *ppos,
.partial = partial,
.flags = flags,
.ops = &page_cache_pipe_buf_ops,
.partial = partial,
.flags = flags,
.ops = &page_cache_pipe_buf_ops,
+ .spd_release = spd_release_page,
};
index = *ppos >> PAGE_CACHE_SHIFT;
};
index = *ppos >> PAGE_CACHE_SHIFT;
@@
-824,13
+830,18
@@
generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
{
struct address_space *mapping = out->f_mapping;
struct inode *inode = mapping->host;
{
struct address_space *mapping = out->f_mapping;
struct inode *inode = mapping->host;
+ int killsuid, killpriv;
ssize_t ret;
ssize_t ret;
- int err;
+ int err
= 0
;
- err = should_remove_suid(out->f_path.dentry);
- if (unlikely(err)) {
+ killpriv = security_inode_need_killpriv(out->f_path.dentry);
+ killsuid = should_remove_suid(out->f_path.dentry);
+ if (unlikely(killsuid || killpriv)) {
mutex_lock(&inode->i_mutex);
mutex_lock(&inode->i_mutex);
- err = __remove_suid(out->f_path.dentry, err);
+ if (killpriv)
+ err = security_inode_killpriv(out->f_path.dentry);
+ if (!err && killsuid)
+ err = __remove_suid(out->f_path.dentry, killsuid);
mutex_unlock(&inode->i_mutex);
if (err)
return err;
mutex_unlock(&inode->i_mutex);
if (err)
return err;
@@
-903,10
+914,6
@@
static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
if (unlikely(ret < 0))
return ret;
if (unlikely(ret < 0))
return ret;
- ret = security_file_permission(out, MAY_WRITE);
- if (unlikely(ret < 0))
- return ret;
-
return out->f_op->splice_write(pipe, out, ppos, len, flags);
}
return out->f_op->splice_write(pipe, out, ppos, len, flags);
}
@@
-929,10
+936,6
@@
static long do_splice_to(struct file *in, loff_t *ppos,
if (unlikely(ret < 0))
return ret;
if (unlikely(ret < 0))
return ret;
- ret = security_file_permission(in, MAY_READ);
- if (unlikely(ret < 0))
- return ret;
-
return in->f_op->splice_read(in, ppos, pipe, len, flags);
}
return in->f_op->splice_read(in, ppos, pipe, len, flags);
}
@@
-1028,7
+1031,9
@@
ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
goto out_release;
}
goto out_release;
}
+done:
pipe->nrbufs = pipe->curbuf = 0;
pipe->nrbufs = pipe->curbuf = 0;
+ file_accessed(in);
return bytes;
out_release:
return bytes;
out_release:
@@
-1044,16
+1049,11
@@
out_release:
buf->ops = NULL;
}
}
buf->ops = NULL;
}
}
- pipe->nrbufs = pipe->curbuf = 0;
- /*
- * If we transferred some data, return the number of bytes:
- */
- if (bytes > 0)
- return bytes;
-
- return ret;
+ if (!bytes)
+ bytes = ret;
+ goto done;
}
EXPORT_SYMBOL(splice_direct_to_actor);
}
EXPORT_SYMBOL(splice_direct_to_actor);
@@
-1179,6
+1179,9
@@
static int copy_from_user_mmap_sem(void *dst, const void __user *src, size_t n)
{
int partial;
{
int partial;
+ if (!access_ok(VERIFY_READ, src, n))
+ return -EFAULT;
+
pagefault_disable();
partial = __copy_from_user_inatomic(dst, src, n);
pagefault_enable();
pagefault_disable();
partial = __copy_from_user_inatomic(dst, src, n);
pagefault_enable();
@@
-1387,6
+1390,11
@@
static long vmsplice_to_user(struct file *file, const struct iovec __user *iov,
break;
}
break;
}
+ if (unlikely(!access_ok(VERIFY_WRITE, base, len))) {
+ error = -EFAULT;
+ break;
+ }
+
sd.len = 0;
sd.total_len = len;
sd.flags = flags;
sd.len = 0;
sd.total_len = len;
sd.flags = flags;
@@
-1435,6
+1443,7
@@
static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov,
.partial = partial,
.flags = flags,
.ops = &user_page_pipe_buf_ops,
.partial = partial,
.flags = flags,
.ops = &user_page_pipe_buf_ops,
+ .spd_release = spd_release_page,
};
pipe = pipe_info(file->f_path.dentry->d_inode);
};
pipe = pipe_info(file->f_path.dentry->d_inode);