* Re: [PATCH] autofs sparse fixes
@ 2003-09-29 18:25 Andries.Brouwer
2003-09-30 23:54 ` Linus Torvalds
0 siblings, 1 reply; 4+ messages in thread
From: Andries.Brouwer @ 2003-09-29 18:25 UTC (permalink / raw)
To: Andries.Brouwer, torvalds; +Cc: linux-kernel
aeb:
/* Our write does not write to user space */
write = (ssize_t (*)(struct file *, const char *, size_t, loff_t *))
file->f_op->write;
lbt:
For cases like this, where we use a kernel pointer and do the
"set_fs(KERNEL_DS)" thing to make a user-pointer routine write
to kernel space, I suggest casting the pointer instead of
the function, along with a comment on the "set_fs()".
set_fs(KERNEL_DS);
/* This cast is legal due to the set_fs()! */
data = (const void __user *) addr;
...->write(file, data, bytes);
set_fs(old_fs);
See? That makes the cast more obvious, and it also makes it obvious
_why_ the cast from kernel->user pointer is ok in this case.
Hmm. Yes. Hmm.
I have to admit that my cast is complicated, one might even say messy,
but as always - when something seems messy it can be made to look
less so by using more lines of code. E.g.,
write = (write_to_kernel_t) file->f_op->write;
looks less intimidating, and write_to_kernel_t can be defined next to
write_proc_t that we have already.
I think I prefer two rights above two wrongs - the declaration
already gives addr the right type - it really does point to kernel space -
but we inherit an incorrect type for file->f_op->write, so have to cast
that.
Hmm. In reality maybe I have no strong feelings either way.
Will see what you do and possibly send some other version
of what you did not apply.
Andries
[Soon things get more interesting. These were the trivial cases,
with set_fs nearby and to a constant value. In other words, cases
where we know precisely what happens and only have to add a cast.
Intermezzo has a lot of code where the same code may be executed
with kernel and with user pointers.
Sendfile can use kernel or user pointers. It is declared with __user
so requires
retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor,
(void __user *) out_file);
(fs/read_write.c:585 -- two wrongs indeed) where the type of pointer
is implicit in the actor. Struct tty_operations has the field
int (*write)(struct tty_struct *tty, int from_user,
const unsigned char *buf, int count);
Etc. Lots of places where static markup does not suffice to show
which pointers point to user space. Pity. That diminishes the value
of __user markup greatly.]
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] autofs sparse fixes
2003-09-29 18:25 [PATCH] autofs sparse fixes Andries.Brouwer
@ 2003-09-30 23:54 ` Linus Torvalds
0 siblings, 0 replies; 4+ messages in thread
From: Linus Torvalds @ 2003-09-30 23:54 UTC (permalink / raw)
To: Andries.Brouwer; +Cc: linux-kernel
On Mon, 29 Sep 2003 Andries.Brouwer@cwi.nl wrote:
>
> I think I prefer two rights above two wrongs - the declaration
> already gives addr the right type - it really does point to kernel space -
> but we inherit an incorrect type for file->f_op->write, so have to cast
> that.
No, the type for file->f_op->write is of the _rigth_ type.
It literally _does_ get the data from user space.
The thing is, what "set_fs(KERNEL_DS)" does is to say "kernel space is now
user space". So the _caller_ will have made user space and kernel space be
the same mapping, exactly so that the write will do the right thing.
[ Yeah, we long since renamed all the "get_fs_byte()" calls to a much more
natural "get_user()" macro, and the "set_fs()" thing should be renamed
too. It obviously makes no sense any more, since we don't use the '%fs'
segment register even on x86 these days, and on other architectures it
never made any sense in the first place. ]
So as a result of the "set_fs()" the kernel pointer literally _becomes_ a
user-pointer. That's what set_fs() is all about. And that's why it is
correct to cast the pointer - but not the function. The function still
takes a user pointer.
Linus
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] autofs sparse fixes
2003-09-28 23:25 Andries.Brouwer
@ 2003-09-29 16:44 ` Linus Torvalds
0 siblings, 0 replies; 4+ messages in thread
From: Linus Torvalds @ 2003-09-29 16:44 UTC (permalink / raw)
To: Andries.Brouwer; +Cc: linux-kernel
For cases like this, where we use a kernel pointer and do the
"set_fs(KERNEL_DS)" thing to mak ea user-pointer routing write to kernel
space, I suggest casting the pointer instead of the function, along with a
comment on the "set_fs()".
Basically, something like this instead:
static int autofs_write(struct file *file, const void *addr, int bytes)
{
const void __user *data;
...
set_fs(KERNEL_DS);
/* This cast is legal due to the set_fs()! */
data = (const void __user *) addr;
...->write(file, data, bytes);
set_fs(old_fs);
}
See? That makes the cast more obvious, and it also makes it obvious _why_
the cast from kernel->user pointer is ok in this case.
Linus
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] autofs sparse fixes
@ 2003-09-28 23:25 Andries.Brouwer
2003-09-29 16:44 ` Linus Torvalds
0 siblings, 1 reply; 4+ messages in thread
From: Andries.Brouwer @ 2003-09-28 23:25 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel
diff -u --recursive --new-file -X /linux/dontdiff a/fs/autofs/root.c b/fs/autofs/root.c
--- a/fs/autofs/root.c Mon Sep 29 01:05:41 2003
+++ b/fs/autofs/root.c Mon Sep 29 01:08:23 2003
@@ -468,7 +468,7 @@
/* Get/set timeout ioctl() operation */
static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi,
- unsigned long *p)
+ unsigned long __user *p)
{
unsigned long ntimeout;
@@ -494,7 +494,7 @@
static inline int autofs_expire_run(struct super_block *sb,
struct autofs_sb_info *sbi,
struct vfsmount *mnt,
- struct autofs_packet_expire *pkt_p)
+ struct autofs_packet_expire __user *pkt_p)
{
struct autofs_dir_ent *ent;
struct autofs_packet_expire pkt;
@@ -547,10 +547,10 @@
case AUTOFS_IOC_PROTOVER: /* Get protocol version */
return autofs_get_protover((int *)arg);
case AUTOFS_IOC_SETTIMEOUT:
- return autofs_get_set_timeout(sbi,(unsigned long *)arg);
+ return autofs_get_set_timeout(sbi,(unsigned long __user *)arg);
case AUTOFS_IOC_EXPIRE:
return autofs_expire_run(inode->i_sb, sbi, filp->f_vfsmnt,
- (struct autofs_packet_expire *)arg);
+ (struct autofs_packet_expire __user *)arg);
default:
return -ENOSYS;
}
diff -u --recursive --new-file -X /linux/dontdiff a/fs/autofs/symlink.c b/fs/autofs/symlink.c
--- a/fs/autofs/symlink.c Mon Sep 29 01:05:41 2003
+++ b/fs/autofs/symlink.c Mon Sep 29 01:08:23 2003
@@ -12,7 +12,8 @@
#include "autofs_i.h"
-static int autofs_readlink(struct dentry *dentry, char *buffer, int buflen)
+static int
+autofs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
{
char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data;
return vfs_readlink(dentry, buffer, buflen, s);
diff -u --recursive --new-file -X /linux/dontdiff a/fs/autofs/waitq.c b/fs/autofs/waitq.c
--- a/fs/autofs/waitq.c Mon Sep 29 01:05:41 2003
+++ b/fs/autofs/waitq.c Mon Sep 29 01:08:23 2003
@@ -44,12 +44,16 @@
autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */
}
+/*
+ * Note: addr not in user space
+ */
static int autofs_write(struct file *file, const void *addr, int bytes)
{
unsigned long sigpipe, flags;
mm_segment_t fs;
const char *data = (const char *)addr;
ssize_t wr = 0;
+ ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
/** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/
@@ -59,8 +63,12 @@
fs = get_fs();
set_fs(KERNEL_DS);
+ /* Our write does not write to user space */
+ write = (ssize_t (*)(struct file *, const char *, size_t, loff_t *))
+ file->f_op->write;
+
while (bytes &&
- (wr = file->f_op->write(file,data,bytes,&file->f_pos)) > 0) {
+ (wr = write(file,data,bytes,&file->f_pos)) > 0) {
data += wr;
bytes -= wr;
}
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2003-09-30 23:57 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-09-29 18:25 [PATCH] autofs sparse fixes Andries.Brouwer
2003-09-30 23:54 ` Linus Torvalds
-- strict thread matches above, loose matches on Subject: below --
2003-09-28 23:25 Andries.Brouwer
2003-09-29 16:44 ` Linus Torvalds
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).