[patch 08/10] unprivileged mounts: make fuse safe

2008-02-05 Thread Miklos Szeredi
From: Miklos Szeredi <[EMAIL PROTECTED]>

Don't require the "user_id=" and "group_id=" options for unprivileged mounts,
but if they are present, verify them for sanity.

Disallow the "allow_other" option for unprivileged mounts.

Document new way of enabling unprivileged mounts for fuse.

Document problems with unprivileged mounts.

Signed-off-by: Miklos Szeredi <[EMAIL PROTECTED]>
Acked-by: Serge Hallyn <[EMAIL PROTECTED]>
---

Index: linux/fs/fuse/inode.c
===
--- linux.orig/fs/fuse/inode.c  2008-02-04 23:47:46.0 +0100
+++ linux/fs/fuse/inode.c   2008-02-04 23:48:06.0 +0100
@@ -359,6 +359,19 @@ static int parse_fuse_opt(char *opt, str
d->max_read = ~0;
d->blksize = FUSE_DEFAULT_BLKSIZE;
 
+   /*
+* For unprivileged mounts use current uid/gid.  Still allow
+* "user_id" and "group_id" options for compatibility, but
+* only if they match these values.
+*/
+   if (!capable(CAP_SYS_ADMIN)) {
+   d->user_id = current->uid;
+   d->user_id_present = 1;
+   d->group_id = current->gid;
+   d->group_id_present = 1;
+
+   }
+
while ((p = strsep(, ",")) != NULL) {
int token;
int value;
@@ -387,6 +400,8 @@ static int parse_fuse_opt(char *opt, str
case OPT_USER_ID:
if (match_int([0], ))
return 0;
+   if (d->user_id_present && d->user_id != value)
+   return 0;
d->user_id = value;
d->user_id_present = 1;
break;
@@ -394,6 +409,8 @@ static int parse_fuse_opt(char *opt, str
case OPT_GROUP_ID:
if (match_int([0], ))
return 0;
+   if (d->group_id_present && d->group_id != value)
+   return 0;
d->group_id = value;
d->group_id_present = 1;
break;
@@ -603,6 +620,10 @@ static int fuse_fill_super(struct super_
if (!parse_fuse_opt((char *) data, , is_bdev))
return -EINVAL;
 
+   /* This is a privileged option */
+   if ((d.flags & FUSE_ALLOW_OTHER) && !capable(CAP_SYS_ADMIN))
+   return -EPERM;
+
if (is_bdev) {
 #ifdef CONFIG_BLOCK
if (!sb_set_blocksize(sb, d.blksize))
Index: linux/Documentation/filesystems/fuse.txt
===
--- linux.orig/Documentation/filesystems/fuse.txt   2008-01-24 
23:58:37.0 +0100
+++ linux/Documentation/filesystems/fuse.txt2008-02-05 19:34:24.0 
+0100
@@ -215,11 +215,87 @@ the filesystem.  There are several ways 
   - Abort filesystem through the FUSE control filesystem.  Most
 powerful method, always works.
 
-How do non-privileged mounts work?
-~~
+Unprivileged fuse mounts
+
 
-Since the mount() system call is a privileged operation, a helper
-program (fusermount) is needed, which is installed setuid root.
+Possible problems with unprivileged fuse mounts
+---
+
+FUSE was designed from the beginning to be safe for unprivileged
+users.  This has also been verified in practice over many years, with
+some distributions enabling unprivileged FUSE mounts by default.
+
+However, there are cases when unprivileged mounting a fuse filesystem
+may be problematic, particularly for multi-user systems with untrusted
+users.  So here are few words of warning:
+
+Due to the design of the process freezer, a hanging (due to network
+problems, etc) or malicious filesystem may prevent suspending to ram
+or hibernation to succeed.  This is not actually unique to FUSE, as
+any hanging network filesystem will have the same affect.
+
+It is not always possible to use kill(2) (not even with SIGKILL) to
+terminate a process using a FUSE filesystem (see section "Interrupting
+filesystem operations" above).  As a special case of the above,
+killing a self-deadlocked FUSE process is not possible, and even
+killall5 will not terminate it.
+
+If the above could pose a threat to the system, it is recommended,
+that unprivileged fuse mounts are not enabled.
+
+Ways of enabling user mounts
+
+
+Now there are two different ways of allowing unprivileged fuse mounts:
+
+ 1) new way: unprivileged mount syscall
+
+ 2) old way: suid-root fusermount utility
+
+Unprivileged mount syscall
+--
+
+To enable this do
+
+  echo 1 > /proc/sys/fs/types/fuse/usermount_safe
+
+or add this line to /etc/sysctl.conf:
+
+  fs.types.fuse.usermount_safe = 1
+
+More information can be found in Documentation/filesystems/proc.txt
+under the /proc/sys/fs/types/ 

[patch 08/10] unprivileged mounts: make fuse safe

2008-02-05 Thread Miklos Szeredi
From: Miklos Szeredi [EMAIL PROTECTED]

Don't require the user_id= and group_id= options for unprivileged mounts,
but if they are present, verify them for sanity.

Disallow the allow_other option for unprivileged mounts.

Document new way of enabling unprivileged mounts for fuse.

Document problems with unprivileged mounts.

Signed-off-by: Miklos Szeredi [EMAIL PROTECTED]
Acked-by: Serge Hallyn [EMAIL PROTECTED]
---

Index: linux/fs/fuse/inode.c
===
--- linux.orig/fs/fuse/inode.c  2008-02-04 23:47:46.0 +0100
+++ linux/fs/fuse/inode.c   2008-02-04 23:48:06.0 +0100
@@ -359,6 +359,19 @@ static int parse_fuse_opt(char *opt, str
d-max_read = ~0;
d-blksize = FUSE_DEFAULT_BLKSIZE;
 
+   /*
+* For unprivileged mounts use current uid/gid.  Still allow
+* user_id and group_id options for compatibility, but
+* only if they match these values.
+*/
+   if (!capable(CAP_SYS_ADMIN)) {
+   d-user_id = current-uid;
+   d-user_id_present = 1;
+   d-group_id = current-gid;
+   d-group_id_present = 1;
+
+   }
+
while ((p = strsep(opt, ,)) != NULL) {
int token;
int value;
@@ -387,6 +400,8 @@ static int parse_fuse_opt(char *opt, str
case OPT_USER_ID:
if (match_int(args[0], value))
return 0;
+   if (d-user_id_present  d-user_id != value)
+   return 0;
d-user_id = value;
d-user_id_present = 1;
break;
@@ -394,6 +409,8 @@ static int parse_fuse_opt(char *opt, str
case OPT_GROUP_ID:
if (match_int(args[0], value))
return 0;
+   if (d-group_id_present  d-group_id != value)
+   return 0;
d-group_id = value;
d-group_id_present = 1;
break;
@@ -603,6 +620,10 @@ static int fuse_fill_super(struct super_
if (!parse_fuse_opt((char *) data, d, is_bdev))
return -EINVAL;
 
+   /* This is a privileged option */
+   if ((d.flags  FUSE_ALLOW_OTHER)  !capable(CAP_SYS_ADMIN))
+   return -EPERM;
+
if (is_bdev) {
 #ifdef CONFIG_BLOCK
if (!sb_set_blocksize(sb, d.blksize))
Index: linux/Documentation/filesystems/fuse.txt
===
--- linux.orig/Documentation/filesystems/fuse.txt   2008-01-24 
23:58:37.0 +0100
+++ linux/Documentation/filesystems/fuse.txt2008-02-05 19:34:24.0 
+0100
@@ -215,11 +215,87 @@ the filesystem.  There are several ways 
   - Abort filesystem through the FUSE control filesystem.  Most
 powerful method, always works.
 
-How do non-privileged mounts work?
-~~
+Unprivileged fuse mounts
+
 
-Since the mount() system call is a privileged operation, a helper
-program (fusermount) is needed, which is installed setuid root.
+Possible problems with unprivileged fuse mounts
+---
+
+FUSE was designed from the beginning to be safe for unprivileged
+users.  This has also been verified in practice over many years, with
+some distributions enabling unprivileged FUSE mounts by default.
+
+However, there are cases when unprivileged mounting a fuse filesystem
+may be problematic, particularly for multi-user systems with untrusted
+users.  So here are few words of warning:
+
+Due to the design of the process freezer, a hanging (due to network
+problems, etc) or malicious filesystem may prevent suspending to ram
+or hibernation to succeed.  This is not actually unique to FUSE, as
+any hanging network filesystem will have the same affect.
+
+It is not always possible to use kill(2) (not even with SIGKILL) to
+terminate a process using a FUSE filesystem (see section Interrupting
+filesystem operations above).  As a special case of the above,
+killing a self-deadlocked FUSE process is not possible, and even
+killall5 will not terminate it.
+
+If the above could pose a threat to the system, it is recommended,
+that unprivileged fuse mounts are not enabled.
+
+Ways of enabling user mounts
+
+
+Now there are two different ways of allowing unprivileged fuse mounts:
+
+ 1) new way: unprivileged mount syscall
+
+ 2) old way: suid-root fusermount utility
+
+Unprivileged mount syscall
+--
+
+To enable this do
+
+  echo 1  /proc/sys/fs/types/fuse/usermount_safe
+
+or add this line to /etc/sysctl.conf:
+
+  fs.types.fuse.usermount_safe = 1
+
+More information can be found in Documentation/filesystems/proc.txt
+under the /proc/sys/fs/types/ heading.  Also see 

Re: [patch 08/10] unprivileged mounts: make fuse safe

2008-01-21 Thread Serge E. Hallyn
Quoting Miklos Szeredi ([EMAIL PROTECTED]):
> From: Miklos Szeredi <[EMAIL PROTECTED]>
> 
> Don't require the "user_id=" and "group_id=" options for unprivileged mounts,
> but if they are present, verify them for sanity.
> 
> Disallow the "allow_other" option for unprivileged mounts.
> 
> FUSE was designed from the beginning to be safe for unprivileged
> users.  This has also been verified in practice over many years, with
> some distributions enabling unprivileged FUSE mounts by default.
> 
> However there are some properties of FUSE, that could make it unsafe
> for certain situations (e.g. multiuser system with untrusted users):
> 
>  - It is not always possible to use kill(2) (not even with SIGKILL) to
>terminate a process using a FUSE filesystem.  However it is
>possible to use any of the following instead:
>  o kill the filesystem daemon
>  o use forced umounting
>  o use the "fusectl" control filesystem
> 
>  - As a special case of the above, killing a self-deadlocked FUSE
>process is not possible, and even killall5 will not terminate it.
> 
>  - Due to the design of the process freezer, a hanging (due to network
>problems, etc) or malicious filesystem may prevent suspending to
>ram or hibernation to succeed.  This is not actually unique to
>FUSE, as any hanging network filesystem will have the same affect.
> 
> If the above could pose a threat to the system, it is recommended,
> that the '/proc/sys/fs/types/fuse/safe' sysctl tunable is not turned
> on, and/or '/dev/fuse' is not made world-readable and writable.
> 
> Signed-off-by: Miklos Szeredi <[EMAIL PROTECTED]>

I was going to say "this should of course be acked by a fuse
maintainer", then I look at MAINTAINERS :)  So never mind.

Acked-by: Serge Hallyn <[EMAIL PROTECTED]>

> ---
> 
> Index: linux/fs/fuse/inode.c
> ===
> --- linux.orig/fs/fuse/inode.c2008-01-16 13:24:52.0 +0100
> +++ linux/fs/fuse/inode.c 2008-01-16 13:25:10.0 +0100
> @@ -357,6 +357,19 @@ static int parse_fuse_opt(char *opt, str
>   d->max_read = ~0;
>   d->blksize = 512;
> 
> + /*
> +  * For unprivileged mounts use current uid/gid.  Still allow
> +  * "user_id" and "group_id" options for compatibility, but
> +  * only if they match these values.
> +  */
> + if (!capable(CAP_SYS_ADMIN)) {
> + d->user_id = current->uid;
> + d->user_id_present = 1;
> + d->group_id = current->gid;
> + d->group_id_present = 1;
> +
> + }
> +
>   while ((p = strsep(, ",")) != NULL) {
>   int token;
>   int value;
> @@ -385,6 +398,8 @@ static int parse_fuse_opt(char *opt, str
>   case OPT_USER_ID:
>   if (match_int([0], ))
>   return 0;
> + if (d->user_id_present && d->user_id != value)
> + return 0;
>   d->user_id = value;
>   d->user_id_present = 1;
>   break;
> @@ -392,6 +407,8 @@ static int parse_fuse_opt(char *opt, str
>   case OPT_GROUP_ID:
>   if (match_int([0], ))
>   return 0;
> + if (d->group_id_present && d->group_id != value)
> + return 0;
>   d->group_id = value;
>   d->group_id_present = 1;
>   break;
> @@ -596,6 +613,10 @@ static int fuse_fill_super(struct super_
>   if (!parse_fuse_opt((char *) data, , is_bdev))
>   return -EINVAL;
> 
> + /* This is a privileged option */
> + if ((d.flags & FUSE_ALLOW_OTHER) && !capable(CAP_SYS_ADMIN))
> + return -EPERM;
> +
>   if (is_bdev) {
>  #ifdef CONFIG_BLOCK
>   if (!sb_set_blocksize(sb, d.blksize))
> 
> --
> -
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to [EMAIL PROTECTED]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 08/10] unprivileged mounts: make fuse safe

2008-01-21 Thread Serge E. Hallyn
Quoting Miklos Szeredi ([EMAIL PROTECTED]):
 From: Miklos Szeredi [EMAIL PROTECTED]
 
 Don't require the user_id= and group_id= options for unprivileged mounts,
 but if they are present, verify them for sanity.
 
 Disallow the allow_other option for unprivileged mounts.
 
 FUSE was designed from the beginning to be safe for unprivileged
 users.  This has also been verified in practice over many years, with
 some distributions enabling unprivileged FUSE mounts by default.
 
 However there are some properties of FUSE, that could make it unsafe
 for certain situations (e.g. multiuser system with untrusted users):
 
  - It is not always possible to use kill(2) (not even with SIGKILL) to
terminate a process using a FUSE filesystem.  However it is
possible to use any of the following instead:
  o kill the filesystem daemon
  o use forced umounting
  o use the fusectl control filesystem
 
  - As a special case of the above, killing a self-deadlocked FUSE
process is not possible, and even killall5 will not terminate it.
 
  - Due to the design of the process freezer, a hanging (due to network
problems, etc) or malicious filesystem may prevent suspending to
ram or hibernation to succeed.  This is not actually unique to
FUSE, as any hanging network filesystem will have the same affect.
 
 If the above could pose a threat to the system, it is recommended,
 that the '/proc/sys/fs/types/fuse/safe' sysctl tunable is not turned
 on, and/or '/dev/fuse' is not made world-readable and writable.
 
 Signed-off-by: Miklos Szeredi [EMAIL PROTECTED]

I was going to say this should of course be acked by a fuse
maintainer, then I look at MAINTAINERS :)  So never mind.

Acked-by: Serge Hallyn [EMAIL PROTECTED]

 ---
 
 Index: linux/fs/fuse/inode.c
 ===
 --- linux.orig/fs/fuse/inode.c2008-01-16 13:24:52.0 +0100
 +++ linux/fs/fuse/inode.c 2008-01-16 13:25:10.0 +0100
 @@ -357,6 +357,19 @@ static int parse_fuse_opt(char *opt, str
   d-max_read = ~0;
   d-blksize = 512;
 
 + /*
 +  * For unprivileged mounts use current uid/gid.  Still allow
 +  * user_id and group_id options for compatibility, but
 +  * only if they match these values.
 +  */
 + if (!capable(CAP_SYS_ADMIN)) {
 + d-user_id = current-uid;
 + d-user_id_present = 1;
 + d-group_id = current-gid;
 + d-group_id_present = 1;
 +
 + }
 +
   while ((p = strsep(opt, ,)) != NULL) {
   int token;
   int value;
 @@ -385,6 +398,8 @@ static int parse_fuse_opt(char *opt, str
   case OPT_USER_ID:
   if (match_int(args[0], value))
   return 0;
 + if (d-user_id_present  d-user_id != value)
 + return 0;
   d-user_id = value;
   d-user_id_present = 1;
   break;
 @@ -392,6 +407,8 @@ static int parse_fuse_opt(char *opt, str
   case OPT_GROUP_ID:
   if (match_int(args[0], value))
   return 0;
 + if (d-group_id_present  d-group_id != value)
 + return 0;
   d-group_id = value;
   d-group_id_present = 1;
   break;
 @@ -596,6 +613,10 @@ static int fuse_fill_super(struct super_
   if (!parse_fuse_opt((char *) data, d, is_bdev))
   return -EINVAL;
 
 + /* This is a privileged option */
 + if ((d.flags  FUSE_ALLOW_OTHER)  !capable(CAP_SYS_ADMIN))
 + return -EPERM;
 +
   if (is_bdev) {
  #ifdef CONFIG_BLOCK
   if (!sb_set_blocksize(sb, d.blksize))
 
 --
 -
 To unsubscribe from this list: send the line unsubscribe linux-fsdevel in
 the body of a message to [EMAIL PROTECTED]
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[patch 08/10] unprivileged mounts: make fuse safe

2008-01-16 Thread Miklos Szeredi
From: Miklos Szeredi <[EMAIL PROTECTED]>

Don't require the "user_id=" and "group_id=" options for unprivileged mounts,
but if they are present, verify them for sanity.

Disallow the "allow_other" option for unprivileged mounts.

FUSE was designed from the beginning to be safe for unprivileged
users.  This has also been verified in practice over many years, with
some distributions enabling unprivileged FUSE mounts by default.

However there are some properties of FUSE, that could make it unsafe
for certain situations (e.g. multiuser system with untrusted users):

 - It is not always possible to use kill(2) (not even with SIGKILL) to
   terminate a process using a FUSE filesystem.  However it is
   possible to use any of the following instead:
 o kill the filesystem daemon
 o use forced umounting
 o use the "fusectl" control filesystem

 - As a special case of the above, killing a self-deadlocked FUSE
   process is not possible, and even killall5 will not terminate it.

 - Due to the design of the process freezer, a hanging (due to network
   problems, etc) or malicious filesystem may prevent suspending to
   ram or hibernation to succeed.  This is not actually unique to
   FUSE, as any hanging network filesystem will have the same affect.

If the above could pose a threat to the system, it is recommended,
that the '/proc/sys/fs/types/fuse/safe' sysctl tunable is not turned
on, and/or '/dev/fuse' is not made world-readable and writable.

Signed-off-by: Miklos Szeredi <[EMAIL PROTECTED]>
---

Index: linux/fs/fuse/inode.c
===
--- linux.orig/fs/fuse/inode.c  2008-01-16 13:24:52.0 +0100
+++ linux/fs/fuse/inode.c   2008-01-16 13:25:10.0 +0100
@@ -357,6 +357,19 @@ static int parse_fuse_opt(char *opt, str
d->max_read = ~0;
d->blksize = 512;
 
+   /*
+* For unprivileged mounts use current uid/gid.  Still allow
+* "user_id" and "group_id" options for compatibility, but
+* only if they match these values.
+*/
+   if (!capable(CAP_SYS_ADMIN)) {
+   d->user_id = current->uid;
+   d->user_id_present = 1;
+   d->group_id = current->gid;
+   d->group_id_present = 1;
+
+   }
+
while ((p = strsep(, ",")) != NULL) {
int token;
int value;
@@ -385,6 +398,8 @@ static int parse_fuse_opt(char *opt, str
case OPT_USER_ID:
if (match_int([0], ))
return 0;
+   if (d->user_id_present && d->user_id != value)
+   return 0;
d->user_id = value;
d->user_id_present = 1;
break;
@@ -392,6 +407,8 @@ static int parse_fuse_opt(char *opt, str
case OPT_GROUP_ID:
if (match_int([0], ))
return 0;
+   if (d->group_id_present && d->group_id != value)
+   return 0;
d->group_id = value;
d->group_id_present = 1;
break;
@@ -596,6 +613,10 @@ static int fuse_fill_super(struct super_
if (!parse_fuse_opt((char *) data, , is_bdev))
return -EINVAL;
 
+   /* This is a privileged option */
+   if ((d.flags & FUSE_ALLOW_OTHER) && !capable(CAP_SYS_ADMIN))
+   return -EPERM;
+
if (is_bdev) {
 #ifdef CONFIG_BLOCK
if (!sb_set_blocksize(sb, d.blksize))

--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[patch 08/10] unprivileged mounts: make fuse safe

2008-01-16 Thread Miklos Szeredi
From: Miklos Szeredi [EMAIL PROTECTED]

Don't require the user_id= and group_id= options for unprivileged mounts,
but if they are present, verify them for sanity.

Disallow the allow_other option for unprivileged mounts.

FUSE was designed from the beginning to be safe for unprivileged
users.  This has also been verified in practice over many years, with
some distributions enabling unprivileged FUSE mounts by default.

However there are some properties of FUSE, that could make it unsafe
for certain situations (e.g. multiuser system with untrusted users):

 - It is not always possible to use kill(2) (not even with SIGKILL) to
   terminate a process using a FUSE filesystem.  However it is
   possible to use any of the following instead:
 o kill the filesystem daemon
 o use forced umounting
 o use the fusectl control filesystem

 - As a special case of the above, killing a self-deadlocked FUSE
   process is not possible, and even killall5 will not terminate it.

 - Due to the design of the process freezer, a hanging (due to network
   problems, etc) or malicious filesystem may prevent suspending to
   ram or hibernation to succeed.  This is not actually unique to
   FUSE, as any hanging network filesystem will have the same affect.

If the above could pose a threat to the system, it is recommended,
that the '/proc/sys/fs/types/fuse/safe' sysctl tunable is not turned
on, and/or '/dev/fuse' is not made world-readable and writable.

Signed-off-by: Miklos Szeredi [EMAIL PROTECTED]
---

Index: linux/fs/fuse/inode.c
===
--- linux.orig/fs/fuse/inode.c  2008-01-16 13:24:52.0 +0100
+++ linux/fs/fuse/inode.c   2008-01-16 13:25:10.0 +0100
@@ -357,6 +357,19 @@ static int parse_fuse_opt(char *opt, str
d-max_read = ~0;
d-blksize = 512;
 
+   /*
+* For unprivileged mounts use current uid/gid.  Still allow
+* user_id and group_id options for compatibility, but
+* only if they match these values.
+*/
+   if (!capable(CAP_SYS_ADMIN)) {
+   d-user_id = current-uid;
+   d-user_id_present = 1;
+   d-group_id = current-gid;
+   d-group_id_present = 1;
+
+   }
+
while ((p = strsep(opt, ,)) != NULL) {
int token;
int value;
@@ -385,6 +398,8 @@ static int parse_fuse_opt(char *opt, str
case OPT_USER_ID:
if (match_int(args[0], value))
return 0;
+   if (d-user_id_present  d-user_id != value)
+   return 0;
d-user_id = value;
d-user_id_present = 1;
break;
@@ -392,6 +407,8 @@ static int parse_fuse_opt(char *opt, str
case OPT_GROUP_ID:
if (match_int(args[0], value))
return 0;
+   if (d-group_id_present  d-group_id != value)
+   return 0;
d-group_id = value;
d-group_id_present = 1;
break;
@@ -596,6 +613,10 @@ static int fuse_fill_super(struct super_
if (!parse_fuse_opt((char *) data, d, is_bdev))
return -EINVAL;
 
+   /* This is a privileged option */
+   if ((d.flags  FUSE_ALLOW_OTHER)  !capable(CAP_SYS_ADMIN))
+   return -EPERM;
+
if (is_bdev) {
 #ifdef CONFIG_BLOCK
if (!sb_set_blocksize(sb, d.blksize))

--
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/