Commit 790d43fd authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] sparse: read_descriptor_t annotation

We have a fun situation with read_descriptor_t - all its instances end
up passed to some actor; these actors use desc->buf as their private
data; there are 5 of them and they expect resp:

        struct lo_read_data *
        struct svc_rqst *
        struct file *
        struct rpc_xprt *
        char __user *

IOW, there is no type safety whatsoever; the field is essentially untyped,
we rely on the fact that actor is chosen by the same code that sets ->buf
and expect it to put something of the right type there.

Right now desc->buf is declared as char __user *.  Moreover, the last
argument of ->sendfile() (what should be stored in ->buf) is void __user *,
even though it's actually _never_ a userland pointer.

If nothing else, ->sendfile() should take void * instead; that alone removes
a bunch of bogus warnings.  I went further and replaced desc->buf with a
union of void * and char __user *.
parent c659d1a8
...@@ -293,7 +293,7 @@ lo_read_actor(read_descriptor_t *desc, struct page *page, ...@@ -293,7 +293,7 @@ lo_read_actor(read_descriptor_t *desc, struct page *page,
unsigned long offset, unsigned long size) unsigned long offset, unsigned long size)
{ {
unsigned long count = desc->count; unsigned long count = desc->count;
struct lo_read_data *p = (struct lo_read_data*)desc->buf; struct lo_read_data *p = desc->arg.data;
struct loop_device *lo = p->lo; struct loop_device *lo = p->lo;
sector_t IV; sector_t IV;
......
...@@ -38,7 +38,7 @@ static long nfs_file_fcntl(int fd, unsigned int cmd, ...@@ -38,7 +38,7 @@ static long nfs_file_fcntl(int fd, unsigned int cmd,
static int nfs_file_open(struct inode *, struct file *); static int nfs_file_open(struct inode *, struct file *);
static int nfs_file_release(struct inode *, struct file *); static int nfs_file_release(struct inode *, struct file *);
static int nfs_file_mmap(struct file *, struct vm_area_struct *); static int nfs_file_mmap(struct file *, struct vm_area_struct *);
static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void __user *); static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t);
static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t); static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t);
static int nfs_file_flush(struct file *); static int nfs_file_flush(struct file *);
...@@ -171,7 +171,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos) ...@@ -171,7 +171,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
static ssize_t static ssize_t
nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count, nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
read_actor_t actor, void __user *target) read_actor_t actor, void *target)
{ {
struct dentry *dentry = filp->f_dentry; struct dentry *dentry = filp->f_dentry;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
......
...@@ -611,7 +611,7 @@ static int ...@@ -611,7 +611,7 @@ static int
nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size) nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size)
{ {
unsigned long count = desc->count; unsigned long count = desc->count;
struct svc_rqst *rqstp = (struct svc_rqst *)desc->buf; struct svc_rqst *rqstp = desc->arg.data;
if (size > count) if (size > count)
size = count; size = count;
......
...@@ -261,7 +261,7 @@ smb_file_mmap(struct file * file, struct vm_area_struct * vma) ...@@ -261,7 +261,7 @@ smb_file_mmap(struct file * file, struct vm_area_struct * vma)
static ssize_t static ssize_t
smb_file_sendfile(struct file *file, loff_t *ppos, smb_file_sendfile(struct file *file, loff_t *ppos,
size_t count, read_actor_t actor, void __user *target) size_t count, read_actor_t actor, void *target)
{ {
struct dentry *dentry = file->f_dentry; struct dentry *dentry = file->f_dentry;
ssize_t status; ssize_t status;
......
...@@ -852,7 +852,10 @@ struct block_device_operations { ...@@ -852,7 +852,10 @@ struct block_device_operations {
typedef struct { typedef struct {
size_t written; size_t written;
size_t count; size_t count;
union {
char __user * buf; char __user * buf;
void *data;
} arg;
int error; int error;
} read_descriptor_t; } read_descriptor_t;
...@@ -883,7 +886,7 @@ struct file_operations { ...@@ -883,7 +886,7 @@ struct file_operations {
int (*lock) (struct file *, int, struct file_lock *); int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void __user *); ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
long (*fcntl)(int fd, unsigned int cmd, long (*fcntl)(int fd, unsigned int cmd,
...@@ -1410,7 +1413,7 @@ extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, lof ...@@ -1410,7 +1413,7 @@ extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, lof
extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos); extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov, ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov,
unsigned long nr_segs, loff_t *ppos); unsigned long nr_segs, loff_t *ppos);
extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void __user *); extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
extern void do_generic_mapping_read(struct address_space *mapping, extern void do_generic_mapping_read(struct address_space *mapping,
struct file_ra_state *, struct file *, struct file_ra_state *, struct file *,
loff_t *, read_descriptor_t *, read_actor_t); loff_t *, read_descriptor_t *, read_actor_t);
......
...@@ -836,9 +836,9 @@ int file_read_actor(read_descriptor_t *desc, struct page *page, ...@@ -836,9 +836,9 @@ int file_read_actor(read_descriptor_t *desc, struct page *page,
* Faults on the destination of a read are common, so do it before * Faults on the destination of a read are common, so do it before
* taking the kmap. * taking the kmap.
*/ */
if (!fault_in_pages_writeable(desc->buf, size)) { if (!fault_in_pages_writeable(desc->arg.buf, size)) {
kaddr = kmap_atomic(page, KM_USER0); kaddr = kmap_atomic(page, KM_USER0);
left = __copy_to_user(desc->buf, kaddr + offset, size); left = __copy_to_user(desc->arg.buf, kaddr + offset, size);
kunmap_atomic(kaddr, KM_USER0); kunmap_atomic(kaddr, KM_USER0);
if (left == 0) if (left == 0)
goto success; goto success;
...@@ -846,7 +846,7 @@ int file_read_actor(read_descriptor_t *desc, struct page *page, ...@@ -846,7 +846,7 @@ int file_read_actor(read_descriptor_t *desc, struct page *page,
/* Do it the slow way */ /* Do it the slow way */
kaddr = kmap(page); kaddr = kmap(page);
left = __copy_to_user(desc->buf, kaddr + offset, size); left = __copy_to_user(desc->arg.buf, kaddr + offset, size);
kunmap(page); kunmap(page);
if (left) { if (left) {
...@@ -856,7 +856,7 @@ int file_read_actor(read_descriptor_t *desc, struct page *page, ...@@ -856,7 +856,7 @@ int file_read_actor(read_descriptor_t *desc, struct page *page,
success: success:
desc->count = count - size; desc->count = count - size;
desc->written += size; desc->written += size;
desc->buf += size; desc->arg.buf += size;
return size; return size;
} }
...@@ -923,7 +923,7 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, ...@@ -923,7 +923,7 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
read_descriptor_t desc; read_descriptor_t desc;
desc.written = 0; desc.written = 0;
desc.buf = iov[seg].iov_base; desc.arg.buf = iov[seg].iov_base;
desc.count = iov[seg].iov_len; desc.count = iov[seg].iov_len;
if (desc.count == 0) if (desc.count == 0)
continue; continue;
...@@ -973,7 +973,7 @@ int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long o ...@@ -973,7 +973,7 @@ int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long o
{ {
ssize_t written; ssize_t written;
unsigned long count = desc->count; unsigned long count = desc->count;
struct file *file = (struct file *) desc->buf; struct file *file = desc->arg.data;
if (size > count) if (size > count)
size = count; size = count;
...@@ -990,7 +990,7 @@ int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long o ...@@ -990,7 +990,7 @@ int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long o
} }
ssize_t generic_file_sendfile(struct file *in_file, loff_t *ppos, ssize_t generic_file_sendfile(struct file *in_file, loff_t *ppos,
size_t count, read_actor_t actor, void __user *target) size_t count, read_actor_t actor, void *target)
{ {
read_descriptor_t desc; read_descriptor_t desc;
...@@ -999,7 +999,7 @@ ssize_t generic_file_sendfile(struct file *in_file, loff_t *ppos, ...@@ -999,7 +999,7 @@ ssize_t generic_file_sendfile(struct file *in_file, loff_t *ppos,
desc.written = 0; desc.written = 0;
desc.count = count; desc.count = count;
desc.buf = target; desc.arg.data = target;
desc.error = 0; desc.error = 0;
do_generic_file_read(in_file, ppos, &desc, actor); do_generic_file_read(in_file, ppos, &desc, actor);
......
...@@ -1474,7 +1474,7 @@ static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count ...@@ -1474,7 +1474,7 @@ static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count
desc.written = 0; desc.written = 0;
desc.count = count; desc.count = count;
desc.buf = buf; desc.arg.buf = buf;
desc.error = 0; desc.error = 0;
do_shmem_file_read(filp, ppos, &desc, file_read_actor); do_shmem_file_read(filp, ppos, &desc, file_read_actor);
...@@ -1484,7 +1484,7 @@ static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count ...@@ -1484,7 +1484,7 @@ static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count
} }
static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos, static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos,
size_t count, read_actor_t actor, void __user *target) size_t count, read_actor_t actor, void *target)
{ {
read_descriptor_t desc; read_descriptor_t desc;
...@@ -1493,7 +1493,7 @@ static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos, ...@@ -1493,7 +1493,7 @@ static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos,
desc.written = 0; desc.written = 0;
desc.count = count; desc.count = count;
desc.buf = target; desc.arg.data = target;
desc.error = 0; desc.error = 0;
do_shmem_file_read(in_file, ppos, &desc, actor); do_shmem_file_read(in_file, ppos, &desc, actor);
......
...@@ -973,7 +973,7 @@ static int ...@@ -973,7 +973,7 @@ static int
tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
unsigned int offset, size_t len) unsigned int offset, size_t len)
{ {
struct rpc_xprt *xprt = (struct rpc_xprt *)rd_desc->buf; struct rpc_xprt *xprt = rd_desc->arg.data;
skb_reader_t desc = { skb_reader_t desc = {
.skb = skb, .skb = skb,
.offset = offset, .offset = offset,
...@@ -1021,7 +1021,7 @@ static void tcp_data_ready(struct sock *sk, int bytes) ...@@ -1021,7 +1021,7 @@ static void tcp_data_ready(struct sock *sk, int bytes)
goto out; goto out;
/* We use rd_desc to pass struct xprt to tcp_data_recv */ /* We use rd_desc to pass struct xprt to tcp_data_recv */
rd_desc.buf = (char *)xprt; rd_desc.arg.data = xprt;
rd_desc.count = 65536; rd_desc.count = 65536;
tcp_read_sock(sk, &rd_desc, tcp_data_recv); tcp_read_sock(sk, &rd_desc, tcp_data_recv);
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment