]> sourceware.org Git - systemtap.git/commitdiff
2007-08-14 David Smith <dsmith@redhat.com>
authordsmith <dsmith>
Tue, 14 Aug 2007 15:27:58 +0000 (15:27 +0000)
committerdsmith <dsmith>
Tue, 14 Aug 2007 15:27:58 +0000 (15:27 +0000)
Merge from setuid-branch.  Changes also by Martin Hunt
<hunt@redhat.com>.

* control.c (_stp_ctl_write): Make sure we don't overflow.
(_stp_ctl_open_cmd): Do not allow multiple opens of the control
file.
(_stp_ctl_write_cmd): Once STP_START is received, ignore
everything except STP_EXIT.  Create another state variable
"initialized". Don't respond to STP_SYMBOLS or STP_MODULES unless
initialized is 0. Also check that current pid is the same as the
pid that did insmod.
(_stp_register_ctl_channel): Bug fix - sets owner/group after
checking for NULL.

* procfs.c (_stp_ctl_write): Make sure we don't overflow.
(_stp_ctl_open_cmd): Do not allow multiple opens of the control
file.
(_stp_ctl_write_cmd): Once STP_START is received, ignore
everything except STP_EXIT.  Create another state variable
"initialized". Don't respond to STP_SYMBOLS or STP_MODULES unless
initialized is 0. Also check that current pid is the same as the
pid that did insmod.
(_stp_register_ctl_channel): Set ownership of cmd file and percpu
files for bulkmode.

* relayfs.c (utt_trace_setup): Set ownership of percpu files.
Improved error handling.
(utt_trace_remove): Improved error checking.

* utt.c (utt_remove_tree): Improved error checking.
(utt_trace_cleanup): Ditto.
(utt_create_buf_file_callback): Set file ownership.
(utt_create_global_buf_file_callback): Set file ownership.

* transport.h: Delcare _stp_uid, _stp_gid, and _stp_init_pid.
* transport.c (_stp_transport_init): Set _stp_uid, _stp_gid, and
_stp_init_pid.

runtime/transport/ChangeLog
runtime/transport/control.c
runtime/transport/procfs.c
runtime/transport/relayfs.c
runtime/transport/symbols.c
runtime/transport/transport.c
runtime/transport/transport.h
runtime/transport/utt.c

index 7ce5be443694921f5ae62e2c53937adfb3608cc9..ee476b29aa6f0d1ac2de8f7e38467fd071494b2f 100644 (file)
@@ -1,3 +1,43 @@
+2007-08-14  David Smith  <dsmith@redhat.com>
+
+       Merge from setuid-branch.  Changes also by Martin Hunt
+       <hunt@redhat.com>.
+
+       * control.c (_stp_ctl_write): Make sure we don't overflow.
+       (_stp_ctl_open_cmd): Do not allow multiple opens of the control
+       file.
+       (_stp_ctl_write_cmd): Once STP_START is received, ignore
+       everything except STP_EXIT.  Create another state variable
+       "initialized". Don't respond to STP_SYMBOLS or STP_MODULES unless
+       initialized is 0. Also check that current pid is the same as the
+       pid that did insmod.
+       (_stp_register_ctl_channel): Bug fix - sets owner/group after
+       checking for NULL.
+
+       * procfs.c (_stp_ctl_write): Make sure we don't overflow.
+       (_stp_ctl_open_cmd): Do not allow multiple opens of the control
+       file.
+       (_stp_ctl_write_cmd): Once STP_START is received, ignore
+       everything except STP_EXIT.  Create another state variable
+       "initialized". Don't respond to STP_SYMBOLS or STP_MODULES unless
+       initialized is 0. Also check that current pid is the same as the
+       pid that did insmod.
+       (_stp_register_ctl_channel): Set ownership of cmd file and percpu
+       files for bulkmode.
+
+       * relayfs.c (utt_trace_setup): Set ownership of percpu files.
+       Improved error handling.
+       (utt_trace_remove): Improved error checking.
+
+       * utt.c (utt_remove_tree): Improved error checking.
+       (utt_trace_cleanup): Ditto.
+       (utt_create_buf_file_callback): Set file ownership.
+       (utt_create_global_buf_file_callback): Set file ownership.
+
+       * transport.h: Delcare _stp_uid, _stp_gid, and _stp_init_pid.
+       * transport.c (_stp_transport_init): Set _stp_uid, _stp_gid, and
+       _stp_init_pid.
+
 2007-07-26  Martin Hunt  <hunt@redhat.com>
 
        Spotted by Ming Chang.
index 68c3b9ae8326fcbbf7decb36e3ec7167c8d48c14..1f7f70bdf3209fc4549b9b05f4b671463249dd3e 100644 (file)
@@ -21,6 +21,7 @@ static ssize_t _stp_ctl_write_cmd (struct file *file, const char __user *buf,
                                    size_t count, loff_t *ppos)
 {
        int type;
+       static int started = 0, initialized = 0;
 
        if (count < sizeof(int))
                return 0;
@@ -28,7 +29,7 @@ static ssize_t _stp_ctl_write_cmd (struct file *file, const char __user *buf,
        if (get_user(type, (int __user *)buf))
                return -EFAULT;
 
-       //kbug ("count:%d type:%d\n", count, type);
+       // kbug ("count:%d type:%d\n", count, type);
 
        if (type == STP_SYMBOLS) {
                count -= sizeof(long);
@@ -41,20 +42,29 @@ static ssize_t _stp_ctl_write_cmd (struct file *file, const char __user *buf,
        switch (type) {
        case STP_START:
        {
-               struct _stp_msg_start st;
-               if (count < sizeof(st))
-                       return 0;
-               if (copy_from_user (&st, buf, sizeof(st)))
-                       return -EFAULT;
-               _stp_handle_start (&st);
+               if (started == 0) {
+                       struct _stp_msg_start st;
+                       if (count < sizeof(st))
+                               return 0;
+                       if (copy_from_user (&st, buf, sizeof(st)))
+                               return -EFAULT;
+                       _stp_handle_start (&st);
+                       started = 1;
+               }
                break;
        }
 
        case STP_SYMBOLS:
-               count = _stp_do_symbols(buf, count);
+               if (initialized == 0 && count && current->pid == _stp_init_pid)
+                       count = _stp_do_symbols(buf, count);
                break;
        case STP_MODULE:
-               count = _stp_do_module(buf, count);
+               if (initialized == 0 && current->pid == _stp_init_pid) {
+                       if (count)
+                               count = _stp_do_module(buf, count);
+                       else
+                               initialized = 1;
+               }
                break;
        case STP_EXIT:
                _stp_exit_flag = 1;
@@ -73,11 +83,13 @@ static ssize_t _stp_ctl_write_cmd (struct file *file, const char __user *buf,
        return count;
 }
 
+#define STP_CTL_BUFFER_SIZE 256
+
 struct _stp_buffer {
        struct list_head list;
        int len;
        int type;
-       char buf[256];
+       char buf[STP_CTL_BUFFER_SIZE];
 };
 
 static DECLARE_WAIT_QUEUE_HEAD(_stp_ctl_wq);
@@ -127,6 +139,10 @@ static int _stp_ctl_write (int type, void *data, unsigned len)
        _stp_ctl_write_dbug(type, data, len);
 #endif
 
+       /* make sure we won't overflow the buffer */
+       if (unlikely(len > STP_CTL_BUFFER_SIZE))
+               return 0;
+
        numtrylock = 0;
        while (!spin_trylock_irqsave (&_stp_pool_lock, flags) && (++numtrylock < MAXTRYLOCK)) 
                ndelay (TRYLOCKDELAY);
@@ -145,7 +161,7 @@ static int _stp_ctl_write (int type, void *data, unsigned len)
        spin_unlock_irqrestore(&_stp_pool_lock, flags);
 
        bptr->type = type;
-       memcpy(bptr->buf, data, min((size_t) len, sizeof(bptr->buf)));
+       memcpy(bptr->buf, data, len);
        bptr->len = len;
        
        /* put it on the pool of ready buffers */
@@ -215,17 +231,23 @@ _stp_ctl_read_cmd (struct file *file, char __user *buf, size_t count, loff_t *pp
        return len;
 }
 
+static int _stp_ctl_opens = 0;
 static int _stp_ctl_open_cmd (struct inode *inode, struct file *file)
 {
+       if (_stp_ctl_opens)
+               return -1;
+
+       _stp_ctl_opens++;
        _stp_pid = current->pid;
        return 0;
 }
 
 static int _stp_ctl_close_cmd (struct inode *inode, struct file *file)
 {
+       if (_stp_ctl_opens)
+               _stp_ctl_opens--;
        _stp_pid = 0;
        return 0;
-
 }
 
 static struct file_operations _stp_ctl_fops_cmd = {
@@ -267,6 +289,8 @@ static int _stp_register_ctl_channel (void)
        _stp_cmd_file = debugfs_create_file("cmd", 0600, _stp_utt->dir, NULL, &_stp_ctl_fops_cmd);
        if (_stp_cmd_file == NULL) 
                goto err0;
+       _stp_cmd_file->d_inode->i_uid = _stp_uid;;
+       _stp_cmd_file->d_inode->i_gid = _stp_gid;
        return 0;
 
 err0:
index 36920707a50aba9b8442869369aa0f668df31424..ca07660f990db8873fd9c948a8f84e0e8d1d194c 100644 (file)
@@ -67,6 +67,7 @@ static ssize_t _stp_ctl_write_cmd (struct file *file, const char __user *buf,
                                    size_t count, loff_t *ppos)
 {
        int type;
+       static int started = 0, initialized = 0;
 
        if (count < sizeof(int))
                return 0;
@@ -87,20 +88,29 @@ static ssize_t _stp_ctl_write_cmd (struct file *file, const char __user *buf,
        switch (type) {
        case STP_START:
        {
-               struct _stp_msg_start st;
-               if (count < sizeof(st))
-                       return 0;
-               if (copy_from_user (&st, buf, sizeof(st)))
-                       return -EFAULT;
-               _stp_handle_start (&st);
+               if (started == 0) {
+                       struct _stp_msg_start st;
+                       if (count < sizeof(st))
+                               return 0;
+                       if (copy_from_user (&st, buf, sizeof(st)))
+                               return -EFAULT;
+                       _stp_handle_start (&st);
+                       started = 1;
+               }
                break;
        }
 
        case STP_SYMBOLS:
-               count = _stp_do_symbols(buf, count);
+               if (initialized == 0 && count && current->pid == _stp_init_pid)
+                       count = _stp_do_symbols(buf, count);
                break;
        case STP_MODULE:
-               count = _stp_do_module(buf, count);
+               if (initialized == 0 && current->pid == _stp_init_pid) {
+                       if (count)
+                               count = _stp_do_module(buf, count);
+                       else
+                               initialized = 1;
+               }
                break;
        case STP_EXIT:
                _stp_exit_flag = 1;
@@ -151,6 +161,10 @@ static int _stp_ctl_write (int type, void *data, int len)
        spin_unlock_irqrestore(&_stp_ready_lock, flags);
 #endif
 
+       /* make sure we won't overflow the buffer */
+       if (unlikely(len > STP_BUFFER_SIZE))
+               return 0;
+
        numtrylock = 0;
        while (!spin_trylock_irqsave (&_stp_pool_lock, flags) && (++numtrylock < MAXTRYLOCK)) 
                ndelay (TRYLOCKDELAY);
@@ -237,17 +251,23 @@ _stp_ctl_read_cmd (struct file *file, char __user *buf, size_t count, loff_t *pp
        return len;
 }
 
+static int _stp_ctl_opens = 0;
 static int _stp_ctl_open_cmd (struct inode *inode, struct file *file)
 {
+       if (_stp_ctl_opens)
+               return -1;
+
+       _stp_ctl_opens++;
        _stp_pid = current->pid;
        return 0;
 }
 
 static int _stp_ctl_close_cmd (struct inode *inode, struct file *file)
 {
+       if (_stp_ctl_opens)
+               _stp_ctl_opens--;
        _stp_pid = 0;
        return 0;
-
 }
 
 static struct file_operations _stp_proc_fops_cmd = {
@@ -378,9 +398,11 @@ static int _stp_register_ctl_channel (void)
        /* now for each cpu "n", create /proc/systemtap/module_name/n  */
        for_each_cpu(i) {
                sprintf(buf, "%d", i);
-               de = create_proc_entry (buf, S_IFREG|S_IRUSR, _stp_proc_mod);
+               de = create_proc_entry (buf, 0600, _stp_proc_mod);
                if (de == NULL) 
                        goto err1;
+               de->uid = _stp_uid;
+               de->gid = _stp_gid;
                de->proc_fops = &_stp_proc_fops;
                de->data = _stp_kmalloc(sizeof(int));
                if (de->data == NULL) {
@@ -393,9 +415,11 @@ static int _stp_register_ctl_channel (void)
 #endif /* STP_BULKMODE */
 
        /* finally create /proc/systemtap/module_name/cmd  */
-       de = create_proc_entry ("cmd", S_IFREG|S_IRUSR|S_IWUSR, _stp_proc_mod);
+       de = create_proc_entry ("cmd", 0600, _stp_proc_mod);
        if (de == NULL) 
                goto err1;
+       de->uid = _stp_uid;
+       de->gid = _stp_gid;
        de->proc_fops = &_stp_proc_fops_cmd;
        return 0;
 
index 2615145cabe81be393975d86e806e4bdf26aea88..28bb0e6570e1d88d67fe1151b92c9af1f1774237 100644 (file)
@@ -80,14 +80,15 @@ static void _stp_remove_relay_root(struct dentry *root)
 struct utt_trace *utt_trace_setup(struct utt_trace_setup *utts)
 {
        struct utt_trace *utt;
+       int i;
 
        utt = _stp_kzalloc(sizeof(*utt));
        if (!utt)
                return NULL;
 
-       utt->utt_tree_root =  _stp_get_root_dir(utts->root);
+       utt->utt_tree_root = _stp_get_root_dir(utts->root);
        if (!utt->utt_tree_root)
-               return NULL;
+               goto err;
 
        utt->dir = relayfs_create_dir(utts->name, utt->utt_tree_root);
        if (!utt->dir)
@@ -95,20 +96,29 @@ struct utt_trace *utt_trace_setup(struct utt_trace_setup *utts)
 
        kbug("relay_open %d %d\n",  utts->buf_size, utts->buf_nr);
 
-       utt->rchan = relay_open("trace", utt->dir, utts->buf_size, utts->buf_nr, 0, &stp_rchan_callbacks);
+       utt->rchan = relay_open("trace", utt->dir, utts->buf_size,
+                               utts->buf_nr, 0, &stp_rchan_callbacks);
        if (!utt->rchan)
-               goto err1;
+               goto err;
+
+       /* now set ownership */
+       for_each_online_cpu(i) {
+               utt->rchan->buf[i]->dentry->d_inode->i_uid = _stp_uid;
+               utt->rchan->buf[i]->dentry->d_inode->i_gid = _stp_gid;
+       }
 
        utt->rchan->private_data = utt;
        utt->trace_state = Utt_trace_setup;
        utts->err = 0;
        return utt;
 
-err1:
-       errk("couldn't create relay channel.\n");
-       _stp_remove_relay_dir(utt->dir);
 err:
-       _stp_remove_relay_root(utt->utt_tree_root);
+       errk("couldn't create relay channel.\n");
+       if (utt->dir)
+               _stp_remove_relay_dir(utt->dir);
+       if (utt->utt_tree_root)
+               _stp_remove_relay_root(utt->utt_tree_root);
+       kfree(utt);
        return NULL;
 }
 
@@ -151,9 +161,12 @@ int utt_trace_remove(struct utt_trace *utt)
 {
        kbug("removing relayfs files. %d\n", utt->trace_state);
        if (utt && (utt->trace_state == Utt_trace_setup || utt->trace_state == Utt_trace_stopped)) {
-               relay_close(utt->rchan);
-               _stp_remove_relay_dir(utt->dir);
-               _stp_remove_relay_root(utt->utt_tree_root);
+               if (utt->rchan)
+                       relay_close(utt->rchan);
+               if (utt->dir)
+                       _stp_remove_relay_dir(utt->dir);
+               if (utt->utt_tree_root)
+                       _stp_remove_relay_root(utt->utt_tree_root);
                kfree(utt);
        }
        return 0;
index 323b48724406f6df93949174134d6d475204514a..1d930183fca7b0eeba9ef826d692336f644fad3c 100644 (file)
@@ -104,6 +104,26 @@ static struct _stp_module * _stp_alloc_module_from_module (struct module *m)
        return _stp_alloc_module(num, datasize);
 }
 
+static void _stp_free_module(struct _stp_module *mod)
+{
+       /* free symbol memory */
+       if (mod->num_symbols) {
+               if (mod->allocated & 1)
+                       vfree(mod->symbols);
+               else
+                       kfree(mod->symbols);
+               if (mod->allocated & 2)
+                       vfree(mod->symbol_data);
+               else
+                       kfree(mod->symbol_data);
+       }
+       if (mod->sections)
+               kfree(mod->sections);
+
+       /* free module memory */
+       kfree(mod);
+}
+
 /* Delete a module and free its memory. */
 /* The lock should already be held before calling this. */
 static void _stp_del_module(struct _stp_module *mod)
@@ -134,23 +154,8 @@ static void _stp_del_module(struct _stp_module *mod)
                _stp_modules_by_addr[i] = _stp_modules_by_addr[i+1];
 
        _stp_num_modules--;
-       
-       /* free symbol memory */
-       if (mod->num_symbols) {
-               if (mod->allocated & 1)
-                       vfree(mod->symbols);
-               else
-                       kfree(mod->symbols);
-               if (mod->allocated & 2)
-                       vfree(mod->symbol_data);
-               else
-                       kfree(mod->symbol_data);
-       }
-       if (mod->sections)
-               kfree(mod->sections);
 
-       /* free module memory */
-       kfree(mod);
+       _stp_free_module(mod);
 }
 
 static void _stp_free_modules(void)
@@ -471,8 +476,10 @@ static int _stp_do_module(const char __user *buf, int count)
                return 0;
        }
 
-       if (_stp_ins_module(mod) < 0)
+       if (_stp_ins_module(mod) < 0) {
+               _stp_free_module(mod);
                return -ENOMEM;
+       }
        
        return count;
 }
index e2737dd6a1f990bd047316341b2befc6628c667b..8df73ed5a4d465181923da3041529ff6db047d78 100644 (file)
@@ -223,6 +223,9 @@ int _stp_transport_init(void)
        int ret;
 
        kbug("transport_init\n");
+       _stp_init_pid = current->pid;
+       _stp_uid = current->uid;
+       _stp_gid = current->gid;
 
        if (_stp_bufsize) {
                unsigned size = _stp_bufsize * 1024 * 1024;
index d1e97edbcb5c44c29ccdb00f6debbbc1fbd9d863..78b011810decee13a3aa3f010fec0b69ecbd83e6 100644 (file)
@@ -23,5 +23,7 @@ static struct dentry *_stp_get_root_dir(const char *name);
 static int _stp_lock_debugfs(void);
 static void _stp_unlock_debugfs(void);
 int _stp_pid = 0;
-
+uid_t _stp_uid = 0;
+gid_t _stp_gid = 0;
+pid_t _stp_init_pid = 0;
 #endif /* _TRANSPORT_TRANSPORT_H_ */
index 2389ccace0e156bc3c630f96a180e23551617030..1ca595924282e7537fb1aec633bbf4afff6f3356 100644 (file)
@@ -45,6 +45,8 @@ static void utt_remove_root(struct utt_trace *utt)
 
 static void utt_remove_tree(struct utt_trace *utt)
 {
+       if (utt == NULL || utt->dir == NULL)
+               return;
        debugfs_remove(utt->dir);
        utt_remove_root(utt);
 }
@@ -65,7 +67,6 @@ static struct dentry *utt_create_tree(struct utt_trace *utt, const char *root, c
         dir = debugfs_create_dir(name, utt->utt_tree_root);
         if (!dir)
                 utt_remove_root(utt);
-
 err:
         return dir;
 }
@@ -73,8 +74,12 @@ err:
 
 void utt_trace_cleanup(struct utt_trace *utt)
 {
-       relay_close(utt->rchan);
-       debugfs_remove(utt->dropped_file);
+       if (utt == NULL)
+               return;
+       if (utt->rchan)
+               relay_close(utt->rchan);
+       if (utt->dropped_file)
+               debugfs_remove(utt->dropped_file);
        utt_remove_tree(utt);
        kfree(utt);
 }
@@ -144,8 +149,13 @@ static struct dentry *utt_create_buf_file_callback(const char *filename,
                                                   struct rchan_buf *buf,
                                                   int *is_global)
 {
-       return debugfs_create_file(filename, mode, parent, buf,
+       struct dentry *file = debugfs_create_file(filename, mode, parent, buf,
                                   &relay_file_operations);
+       if (file) {
+               file->d_inode->i_uid = _stp_uid;
+               file->d_inode->i_gid = _stp_gid;
+       }
+       return  file;
 }
 
 static struct dentry *utt_create_global_buf_file_callback(const char *filename,
@@ -154,9 +164,15 @@ static struct dentry *utt_create_global_buf_file_callback(const char *filename,
                                                          struct rchan_buf *buf,
                                                          int *is_global)
 {
+       struct dentry *file; 
        *is_global = 1;
-       return debugfs_create_file(filename, mode, parent, buf,
+       file = debugfs_create_file(filename, mode, parent, buf,
                                   &relay_file_operations);
+       if (file) {
+               file->d_inode->i_uid = _stp_uid;
+               file->d_inode->i_gid = _stp_gid;
+       }
+       return  file;
 }
 
 static struct rchan_callbacks utt_relay_callbacks = {
This page took 0.046309 seconds and 5 git commands to generate.