2005-11-27 18:57:48

by Mohamed El Dawy

[permalink] [raw]
Subject: What's wrong with this really simple function?

Hi,
I have created this 5-liner system call, which basically opens a
file, write "Hello World" to it, and then returns. That's all.

Now, when I actually call it, it creates the file successfully but
writes nothing to it. The file is created and is only zero bytes. So,
either write didn't write, or close didn't close. Any help would be
greatly appreciated.

#define SUCCESS 0
#define CANT_OPEN_FILE 1
#define YOU_ARE_NOT_ROOT 3
#define OTHER_STUPID_ERROR 4

asmlinkage long sys_dump(char * filename)
{
int fd;
if(!capable(CAP_SYS_ADMIN))
return YOU_ARE_NOT_ROOT;

fd=sys_open(filename,O_CREAT|O_WRONLY|O_TRUNC,S_IRWXU);
if(fd==-1)
return CANT_OPEN_FILE;

if(sys_write(fd,"Hello World From inside the kernel!",35)==0)
{
sys_close(fd);
return OTHER_STUPID_ERROR;
}

sys_close(fd);
return SUCCESS;
}


2005-11-28 01:02:54

by Robert Hancock

[permalink] [raw]
Subject: Re: What's wrong with this really simple function?

Mohamed El Dawy wrote:
> Hi,
> I have created this 5-liner system call, which basically opens a
> file, write "Hello World" to it, and then returns. That's all.
>
> Now, when I actually call it, it creates the file successfully but
> writes nothing to it. The file is created and is only zero bytes. So,
> either write didn't write, or close didn't close. Any help would be
> greatly appreciated.

Well, the main thing wrong is that you are writing to a file from inside
the kernel, that is just wrong.. However likely the reason why the write
didn't work is that it expects an address inside userspace memory and
you've given it a character literal which is inside the kernel address
space.

--
Robert Hancock Saskatoon, SK, Canada
To email, remove "nospam" from [email protected]
Home Page: http://www.roberthancock.com/

2005-11-28 07:55:09

by Juergen Quade

[permalink] [raw]
Subject: Re: What's wrong with this really simple function?

On Sun, Nov 27, 2005 at 12:57:47PM -0600, Mohamed El Dawy wrote:
> Hi,
> I have created this 5-liner system call, which basically opens a
> file, write "Hello World" to it, and then returns. That's all.
>
> Now, when I actually call it, it creates the file successfully but
> writes nothing to it. The file is created and is only zero bytes. So,
> either write didn't write, or close didn't close. Any help would be
> greatly appreciated.
> ...

The following (module-) code will create and write a file from
inside a kernel. Ok -- you know -- you should not use it
without really good reasons ...

Juergen.

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/fs.h>
#include <asm/uaccess.h>

static char filename[255];
module_param_string( filename, filename, sizeof(filename), 666 );
struct file *log_file;

static int __init mod_init(void)
{
mm_segment_t oldfs;

if( filename[0]=='\0' )
strncpy( filename, "/tmp/kernel_file", sizeof(filename) );
printk("opening filename: %s\n", filename);
log_file = filp_open( filename, O_WRONLY | O_CREAT, 0644 );
printk("log_file: %p\n", log_file );
if( IS_ERR( log_file ) )
return -EIO;

oldfs = get_fs();
set_fs( KERNEL_DS );
vfs_write( log_file, "hallo\n", 6, &log_file->f_pos );
set_fs( oldfs );
filp_close( log_file, NULL );
return 0;
}

static void __exit mod_exit(void)
{
}
module_init( mod_init );
module_exit( mod_exit );
MODULE_LICENSE("GPL");
/* vim:set ts=4 sw=4 ic aw: */

2005-11-28 12:46:08

by Nikita Danilov

[permalink] [raw]
Subject: Re: What's wrong with this really simple function?

Juergen Quade writes:
> On Sun, Nov 27, 2005 at 12:57:47PM -0600, Mohamed El Dawy wrote:
> > Hi,
> > I have created this 5-liner system call, which basically opens a
> > file, write "Hello World" to it, and then returns. That's all.
> >
> > Now, when I actually call it, it creates the file successfully but
> > writes nothing to it. The file is created and is only zero bytes. So,
> > either write didn't write, or close didn't close. Any help would be
> > greatly appreciated.
> > ...
>
> The following (module-) code will create and write a file from
> inside a kernel. Ok -- you know -- you should not use it
> without really good reasons ...
>
> Juergen.
>
> #include <linux/module.h>
> #include <linux/moduleparam.h>
> #include <linux/fs.h>
> #include <asm/uaccess.h>
>
> static char filename[255];
> module_param_string( filename, filename, sizeof(filename), 666 );
> struct file *log_file;
>
> static int __init mod_init(void)
> {
> mm_segment_t oldfs;
>
> if( filename[0]=='\0' )
> strncpy( filename, "/tmp/kernel_file", sizeof(filename) );
> printk("opening filename: %s\n", filename);
> log_file = filp_open( filename, O_WRONLY | O_CREAT, 0644 );
> printk("log_file: %p\n", log_file );
> if( IS_ERR( log_file ) )
> return -EIO;

This code is trivially exploitable: /tmp is usually a world-writable
directory, and everybody can do

$ ln -s /etc/shadow /tmp/kernel_file

or even

$ ln /etc/shadow /tmp/kernel_file

provided that /tmp and /etc are on the same file system.

Please do not use it.

Nikita.

2005-11-28 13:09:46

by linux-os (Dick Johnson)

[permalink] [raw]
Subject: Re: What's wrong with this really simple function?


On Mon, 28 Nov 2005, Nikita Danilov wrote:

> Juergen Quade writes:
> > On Sun, Nov 27, 2005 at 12:57:47PM -0600, Mohamed El Dawy wrote:
> > > Hi,
> > > I have created this 5-liner system call, which basically opens a
> > > file, write "Hello World" to it, and then returns. That's all.
> > >
> > > Now, when I actually call it, it creates the file successfully but
> > > writes nothing to it. The file is created and is only zero bytes. So,
> > > either write didn't write, or close didn't close. Any help would be
> > > greatly appreciated.
> > > ...
> >
> > The following (module-) code will create and write a file from
> > inside a kernel. Ok -- you know -- you should not use it
> > without really good reasons ...
> >
> > Juergen.
> >
> > #include <linux/module.h>
> > #include <linux/moduleparam.h>
> > #include <linux/fs.h>
> > #include <asm/uaccess.h>
> >
> > static char filename[255];
> > module_param_string( filename, filename, sizeof(filename), 666 );
> > struct file *log_file;
> >
> > static int __init mod_init(void)
> > {
> > mm_segment_t oldfs;
> >
> > if( filename[0]=='\0' )
> > strncpy( filename, "/tmp/kernel_file", sizeof(filename) );
> > printk("opening filename: %s\n", filename);
> > log_file = filp_open( filename, O_WRONLY | O_CREAT, 0644 );
> > printk("log_file: %p\n", log_file );
> > if( IS_ERR( log_file ) )
> > return -EIO;
>
> This code is trivially exploitable: /tmp is usually a world-writable
> directory, and everybody can do
>
> $ ln -s /etc/shadow /tmp/kernel_file
>
> or even
>
> $ ln /etc/shadow /tmp/kernel_file
>
> provided that /tmp and /etc are on the same file system.
>
> Please do not use it.
>
> Nikita.

Also, this has become a FAQ. One needs a context with which to
associate file descriptors and even file buffers. Whose did he
steal? When he finds out, he will find the buffer that never
got written to the file.

Again, to read/write files from inside the kernel either create
a kernel thread, steal init's context, or don't.


Cheers,
Dick Johnson
Penguin : Linux version 2.6.13.4 on an i686 machine (5589.55 BogoMips).
Warning : 98.36% of all statistics are fiction.
.

****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to [email protected] - and destroy all copies of this information, including any attachments, without reading or disclosing them.

Thank you.