Backport fixes to work with kernel 3.7
This commit is contained in:
		
							parent
							
								
									d414f9c050
								
							
						
					
					
						commit
						90a95910e5
					
				
							
								
								
									
										203
									
								
								systemtap-2.0-missing-VM_EXECUTABLE.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								systemtap-2.0-missing-VM_EXECUTABLE.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,203 @@ | |||||||
|  | commit 6a4267cb9967c4f330e40d5aa8d9be265b3c2997 | ||||||
|  | Author: Josh Stone <jistone@redhat.com> | ||||||
|  | Date:   Fri Oct 12 14:45:55 2012 -0700 | ||||||
|  | 
 | ||||||
|  |     PR14712 backport for release-2.0 | ||||||
|  |      | ||||||
|  |         529c7ea     Fix for kernels without VM_EXECUTABLE | ||||||
|  |         3df148c     Fix the include order so vma tracking works | ||||||
|  |         1f13ff7     Correct the bug number in a comment | ||||||
|  | 
 | ||||||
|  | diff --git a/runtime/linux/task_finder.c b/runtime/linux/task_finder.c
 | ||||||
|  | index 2b1e22f..e2e575a 100644
 | ||||||
|  | --- a/runtime/linux/task_finder.c
 | ||||||
|  | +++ b/runtime/linux/task_finder.c
 | ||||||
|  | @@ -26,6 +26,7 @@
 | ||||||
|  |  #include "syscall.h" | ||||||
|  |  #include "utrace_compatibility.h" | ||||||
|  |  #include "task_finder_map.c" | ||||||
|  | +#include "task_finder_vma.c"
 | ||||||
|  |   | ||||||
|  |  static LIST_HEAD(__stp_task_finder_list); | ||||||
|  |   | ||||||
|  | @@ -440,7 +441,7 @@ __stp_task_finder_cleanup(void)
 | ||||||
|  |  static char * | ||||||
|  |  __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen) | ||||||
|  |  { | ||||||
|  | -	struct vm_area_struct *vma;
 | ||||||
|  | +	struct file *vm_file;
 | ||||||
|  |  	char *rc = NULL; | ||||||
|  |   | ||||||
|  |  	// The down_read() function can sleep, so we'll call | ||||||
|  | @@ -451,17 +452,12 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
 | ||||||
|  |  		return ERR_PTR(-ENOENT); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	vma = mm->mmap;
 | ||||||
|  | -	while (vma) {
 | ||||||
|  | -		if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
 | ||||||
|  | -			break;
 | ||||||
|  | -		vma = vma->vm_next;
 | ||||||
|  | -	}
 | ||||||
|  | -	if (vma) {
 | ||||||
|  | +	vm_file = stap_find_exe_file(mm);
 | ||||||
|  | +	if (vm_file) {
 | ||||||
|  |  #ifdef STAPCONF_DPATH_PATH | ||||||
|  | -		rc = d_path(&(vma->vm_file->f_path), buf, buflen);
 | ||||||
|  | +		rc = d_path(&(vm_file->f_path), buf, buflen);
 | ||||||
|  |  #else | ||||||
|  | -		rc = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt,
 | ||||||
|  | +		rc = d_path(vm_file->f_dentry, vm_file->f_vfsmnt,
 | ||||||
|  |  			    buf, buflen); | ||||||
|  |  #endif | ||||||
|  |  	} | ||||||
|  | diff --git a/runtime/linux/task_finder2.c b/runtime/linux/task_finder2.c
 | ||||||
|  | index 680b428..27ba2d2 100644
 | ||||||
|  | --- a/runtime/linux/task_finder2.c
 | ||||||
|  | +++ b/runtime/linux/task_finder2.c
 | ||||||
|  | @@ -11,6 +11,7 @@
 | ||||||
|  |  #endif | ||||||
|  |  #include "syscall.h" | ||||||
|  |  #include "task_finder_map.c" | ||||||
|  | +#include "task_finder_vma.c"
 | ||||||
|  |   | ||||||
|  |  static LIST_HEAD(__stp_task_finder_list); | ||||||
|  |   | ||||||
|  | @@ -425,7 +426,7 @@ __stp_task_finder_cleanup(void)
 | ||||||
|  |  static char * | ||||||
|  |  __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen) | ||||||
|  |  { | ||||||
|  | -	struct vm_area_struct *vma;
 | ||||||
|  | +	struct file *vm_file;
 | ||||||
|  |  	char *rc = NULL; | ||||||
|  |   | ||||||
|  |  	// The down_read() function can sleep, so we'll call | ||||||
|  | @@ -436,17 +437,12 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
 | ||||||
|  |  		return ERR_PTR(-ENOENT); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	vma = mm->mmap;
 | ||||||
|  | -	while (vma) {
 | ||||||
|  | -		if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
 | ||||||
|  | -			break;
 | ||||||
|  | -		vma = vma->vm_next;
 | ||||||
|  | -	}
 | ||||||
|  | -	if (vma) {
 | ||||||
|  | +	vm_file = stap_find_exe_file(mm);
 | ||||||
|  | +	if (vm_file) {
 | ||||||
|  |  #ifdef STAPCONF_DPATH_PATH | ||||||
|  | -		rc = d_path(&(vma->vm_file->f_path), buf, buflen);
 | ||||||
|  | +		rc = d_path(&(vm_file->f_path), buf, buflen);
 | ||||||
|  |  #else | ||||||
|  | -		rc = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt,
 | ||||||
|  | +		rc = d_path(vm_file->f_dentry, vm_file->f_vfsmnt,
 | ||||||
|  |  			    buf, buflen); | ||||||
|  |  #endif | ||||||
|  |  	} | ||||||
|  | diff --git a/runtime/linux/uprobes-common.c b/runtime/linux/uprobes-common.c
 | ||||||
|  | index 64b62cc..cdfb5a6 100644
 | ||||||
|  | --- a/runtime/linux/uprobes-common.c
 | ||||||
|  | +++ b/runtime/linux/uprobes-common.c
 | ||||||
|  | @@ -77,13 +77,10 @@ static int stap_uprobe_change_plus (struct task_struct *tsk, unsigned long reloc
 | ||||||
|  |   | ||||||
|  |      sdt_sem_pid = (sups->return_p ? sup->urp.u.pid : sup->up.pid); | ||||||
|  |      if (sups->sdt_sem_offset && (sdt_sem_pid != tsk->tgid || sup->sdt_sem_address == 0)) { | ||||||
|  | -      /* If the probe is in the executable itself, the offset *is* the address. */
 | ||||||
|  | -      if (vm_flags & VM_EXECUTABLE) {
 | ||||||
|  | -        sup->sdt_sem_address = relocation + sups->sdt_sem_offset;
 | ||||||
|  | -      }
 | ||||||
|  | -      else {
 | ||||||
|  | -        sup->sdt_sem_address = (relocation - offset) + sups->sdt_sem_offset;
 | ||||||
|  | -      }
 | ||||||
|  | +      /* If the probe is in an ET_EXEC binary, then the sdt_sem_offset already
 | ||||||
|  | +       * is a real address.  But stap_uprobe_process_found calls us in this
 | ||||||
|  | +       * case with relocation=offset=0, so we don't have to worry about it.  */
 | ||||||
|  | +      sup->sdt_sem_address = (relocation - offset) + sups->sdt_sem_offset;
 | ||||||
|  |      } /* sdt_sem_offset */ | ||||||
|  |      if (slotted_p) { | ||||||
|  |        struct stap_uprobe *sup = & stap_uprobes[i]; | ||||||
|  | diff --git a/runtime/linux/uprobes-inode.c b/runtime/linux/uprobes-inode.c
 | ||||||
|  | index 578123c..9d4d867 100644
 | ||||||
|  | --- a/runtime/linux/uprobes-inode.c
 | ||||||
|  | +++ b/runtime/linux/uprobes-inode.c
 | ||||||
|  | @@ -406,9 +406,14 @@ stapiu_change_plus(struct stapiu_target* target, struct task_struct *task,
 | ||||||
|  |  		if (!p->tgid) { | ||||||
|  |  			p->tgid = task->tgid; | ||||||
|  |  			p->relocation = relocation; | ||||||
|  | -			p->base = relocation;
 | ||||||
|  | -			if (!(vm_flags & VM_EXECUTABLE))
 | ||||||
|  | -				p->base -= offset;
 | ||||||
|  | +
 | ||||||
|  | +                        /* The base is used for relocating semaphores.  If the
 | ||||||
|  | +                         * probe is in an ET_EXEC binary, then that offset
 | ||||||
|  | +                         * already is a real address.  But stapiu_process_found
 | ||||||
|  | +                         * calls us in this case with relocation=offset=0, so
 | ||||||
|  | +                         * we don't have to worry about it.  */
 | ||||||
|  | +			p->base = relocation - offset;
 | ||||||
|  | +
 | ||||||
|  |  			list_add(&p->target_process, &target->processes); | ||||||
|  |  			break; | ||||||
|  |  		} | ||||||
|  | @@ -491,7 +496,7 @@ static struct inode *
 | ||||||
|  |  stapiu_get_task_inode(struct task_struct *task) | ||||||
|  |  { | ||||||
|  |  	struct mm_struct *mm; | ||||||
|  | -	struct vm_area_struct *vma;
 | ||||||
|  | +	struct file* vm_file;
 | ||||||
|  |  	struct inode *inode = NULL; | ||||||
|  |   | ||||||
|  |  	// Grab the inode associated with the task. | ||||||
|  | @@ -507,15 +512,9 @@ stapiu_get_task_inode(struct task_struct *task)
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	down_read(&mm->mmap_sem); | ||||||
|  | -	vma = mm->mmap;
 | ||||||
|  | -	while (vma) {
 | ||||||
|  | -		if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file
 | ||||||
|  | -		    && vma->vm_file->f_path.dentry != NULL) {
 | ||||||
|  | -			inode = vma->vm_file->f_path.dentry->d_inode;
 | ||||||
|  | -			break;
 | ||||||
|  | -		}
 | ||||||
|  | -		vma = vma->vm_next;
 | ||||||
|  | -	}
 | ||||||
|  | +	vm_file = stap_find_exe_file(mm);
 | ||||||
|  | +	if (vm_file && vm_file->f_path.dentry)
 | ||||||
|  | +		inode = vm_file->f_path.dentry->d_inode;
 | ||||||
|  |   | ||||||
|  |  	up_read(&mm->mmap_sem); | ||||||
|  |  	return inode; | ||||||
|  | diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c
 | ||||||
|  | index 7c872ba..0db35a0 100644
 | ||||||
|  | --- a/runtime/task_finder_vma.c
 | ||||||
|  | +++ b/runtime/task_finder_vma.c
 | ||||||
|  | @@ -1,3 +1,6 @@
 | ||||||
|  | +#ifndef TASK_FINDER_VMA_C
 | ||||||
|  | +#define TASK_FINDER_VMA_C
 | ||||||
|  | +
 | ||||||
|  |  #include <linux/list.h> | ||||||
|  |  #include <linux/jhash.h> | ||||||
|  |  #include <linux/spinlock.h> | ||||||
|  | @@ -371,3 +374,23 @@ stap_drop_vma_maps(struct task_struct *tsk)
 | ||||||
|  |  	write_unlock_irqrestore(&__stp_tf_vma_lock, flags); | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  | +
 | ||||||
|  | +/* Find the main executable for this mm.
 | ||||||
|  | + * NB: mmap_sem should be held already. */
 | ||||||
|  | +static struct file*
 | ||||||
|  | +stap_find_exe_file(struct mm_struct* mm)
 | ||||||
|  | +{
 | ||||||
|  | +	/* VM_EXECUTABLE was killed in kernel commit e9714acf, but in kernels
 | ||||||
|  | +	 * that new we can just use mm->exe_file anyway.  (PR14712)  */
 | ||||||
|  | +#ifdef VM_EXECUTABLE
 | ||||||
|  | +	struct vm_area_struct *vma;
 | ||||||
|  | +	for (vma = mm->mmap; vma; vma = vma->vm_next)
 | ||||||
|  | +		if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
 | ||||||
|  | +			return vma->vm_file;
 | ||||||
|  | +	return NULL;
 | ||||||
|  | +#else
 | ||||||
|  | +	return mm->exe_file;
 | ||||||
|  | +#endif
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +#endif /* TASK_FINDER_VMA_C */
 | ||||||
							
								
								
									
										448
									
								
								systemtap-2.0-mode-0700-debugfs.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										448
									
								
								systemtap-2.0-mode-0700-debugfs.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,448 @@ | |||||||
|  | commit 35729a95369c30133a3485bbfbfc1ebd01048690 | ||||||
|  | Author: Josh Stone <jistone@redhat.com> | ||||||
|  | Date:   Wed Jan 16 09:50:09 2013 -0800 | ||||||
|  | 
 | ||||||
|  |     PR14245 backport for release-2.0 | ||||||
|  |      | ||||||
|  |         56629dd     have configury look for openat(2) syscall | ||||||
|  |         c5f7c84     support /sys/kernel/debug mounted 0700 | ||||||
|  |         00d577a     fix staprun->stapio -F<fd> passing for -A (attach) mode | ||||||
|  |         d7f9b5d     clean up error messages for staprun -d SOMETHING_AWFUL | ||||||
|  |         17986f2     stapio should not pass inherited relay_basedir_fd | ||||||
|  | 
 | ||||||
|  | diff --git a/config.in b/config.in
 | ||||||
|  | index 25c4cd3..c87460a 100644
 | ||||||
|  | --- a/config.in
 | ||||||
|  | +++ b/config.in
 | ||||||
|  | @@ -65,6 +65,9 @@
 | ||||||
|  |  /* Define to 1 if you have the nss libraries. */ | ||||||
|  |  #undef HAVE_NSS | ||||||
|  |   | ||||||
|  | +/* Define to 1 if you have the `openat' function. */
 | ||||||
|  | +#undef HAVE_OPENAT
 | ||||||
|  | +
 | ||||||
|  |  /* Define to 1 if you have the `ppoll' function. */ | ||||||
|  |  #undef HAVE_PPOLL | ||||||
|  |   | ||||||
|  | diff --git a/configure b/configure
 | ||||||
|  | index 33112c7..a942440 100755
 | ||||||
|  | --- a/configure
 | ||||||
|  | +++ b/configure
 | ||||||
|  | @@ -8864,6 +8864,17 @@ _ACEOF
 | ||||||
|  |  fi | ||||||
|  |  done | ||||||
|  |   | ||||||
|  | +for ac_func in openat
 | ||||||
|  | +do :
 | ||||||
|  | +  ac_fn_c_check_func "$LINENO" "openat" "ac_cv_func_openat"
 | ||||||
|  | +if test "x$ac_cv_func_openat" = xyes; then :
 | ||||||
|  | +  cat >>confdefs.h <<_ACEOF
 | ||||||
|  | +#define HAVE_OPENAT 1
 | ||||||
|  | +_ACEOF
 | ||||||
|  | +
 | ||||||
|  | +fi
 | ||||||
|  | +done
 | ||||||
|  | +
 | ||||||
|  |   | ||||||
|  |  if test "${enable_prologues+set}" != set; then | ||||||
|  |    { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if prologue searching should be the default" >&5 | ||||||
|  | diff --git a/configure.ac b/configure.ac
 | ||||||
|  | index 8527763..e7ce384 100644
 | ||||||
|  | --- a/configure.ac
 | ||||||
|  | +++ b/configure.ac
 | ||||||
|  | @@ -32,6 +32,7 @@ AC_SYS_LARGEFILE
 | ||||||
|  |  AM_GNU_GETTEXT(external) | ||||||
|  |  AM_GNU_GETTEXT_VERSION(0.17) | ||||||
|  |  AC_CHECK_FUNCS(ppoll) | ||||||
|  | +AC_CHECK_FUNCS(openat)
 | ||||||
|  |   | ||||||
|  |  dnl Handle the prologues option. | ||||||
|  |  dnl | ||||||
|  | diff --git a/staprun/common.c b/staprun/common.c
 | ||||||
|  | index ba59c88..f6acb6f 100644
 | ||||||
|  | --- a/staprun/common.c
 | ||||||
|  | +++ b/staprun/common.c
 | ||||||
|  | @@ -38,6 +38,7 @@ off_t fsize_max;
 | ||||||
|  |  int fnum_max; | ||||||
|  |  int remote_id; | ||||||
|  |  const char *remote_uri; | ||||||
|  | +int relay_basedir_fd;
 | ||||||
|  |   | ||||||
|  |  /* module variables */ | ||||||
|  |  char *modname = NULL; | ||||||
|  | @@ -132,8 +133,13 @@ void parse_args(int argc, char **argv)
 | ||||||
|  |  	fnum_max = 0; | ||||||
|  |          remote_id = -1; | ||||||
|  |          remote_uri = NULL; | ||||||
|  | +        relay_basedir_fd = -1;
 | ||||||
|  |   | ||||||
|  | -	while ((c = getopt(argc, argv, "ALu::vb:t:dc:o:x:S:DwRr:VT:")) != EOF) {
 | ||||||
|  | +	while ((c = getopt(argc, argv, "ALu::vb:t:dc:o:x:S:DwRr:VT:"
 | ||||||
|  | +#ifdef HAVE_OPENAT
 | ||||||
|  | +                           "F:"
 | ||||||
|  | +#endif
 | ||||||
|  | +                        )) != EOF) {
 | ||||||
|  |  		switch (c) { | ||||||
|  |  		case 'u': | ||||||
|  |  			need_uprobes = 1; | ||||||
|  | @@ -179,6 +185,13 @@ void parse_args(int argc, char **argv)
 | ||||||
|  |  		case 'D': | ||||||
|  |  			daemon_mode = 1; | ||||||
|  |  			break; | ||||||
|  | +		case 'F':
 | ||||||
|  | +			relay_basedir_fd = atoi(optarg);
 | ||||||
|  | +			if (relay_basedir_fd < 0) {
 | ||||||
|  | +				err(_("Invalid file descriptor option '%s'.\n"), optarg);
 | ||||||
|  | +				usage(argv[0]);
 | ||||||
|  | +			}
 | ||||||
|  | +			break;
 | ||||||
|  |  		case 'S': | ||||||
|  |  			fsize_max = strtoul(optarg, &s, 10); | ||||||
|  |  			fsize_max <<= 20; | ||||||
|  | @@ -327,6 +340,9 @@ void usage(char *prog)
 | ||||||
|  |          "-T timeout      Specifies upper limit on amount of time reader thread\n" | ||||||
|  |          "                will wait for new full trace buffer. Value should be an\n" | ||||||
|  |          "                integer >= 1, which is timeout value in ms. Default 200ms.\n\n" | ||||||
|  | +#ifdef HAVE_OPENAT
 | ||||||
|  | +        "-F fd           Specifies file descriptor for module relay directory\n"
 | ||||||
|  | +#endif
 | ||||||
|  |  	"MODULE can be either a module name or a module path.  If a\n" | ||||||
|  |  	"module name is used, it is searched in the following directory:\n")); | ||||||
|  |          { | ||||||
|  | diff --git a/staprun/ctl.c b/staprun/ctl.c
 | ||||||
|  | index 9cc87ea..235748b 100644
 | ||||||
|  | --- a/staprun/ctl.c
 | ||||||
|  | +++ b/staprun/ctl.c
 | ||||||
|  | @@ -7,23 +7,64 @@
 | ||||||
|  |   * Public License (GPL); either version 2, or (at your option) any | ||||||
|  |   * later version. | ||||||
|  |   * | ||||||
|  | - * Copyright (C) 2007 Red Hat Inc.
 | ||||||
|  | + * Copyright (C) 2012 Red Hat Inc.
 | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  |  #include "staprun.h" | ||||||
|  |   | ||||||
|  | +#define CTL_CHANNEL_NAME ".cmd"
 | ||||||
|  | +
 | ||||||
|  |  int init_ctl_channel(const char *name, int verb) | ||||||
|  |  { | ||||||
|  |  	char buf[PATH_MAX]; | ||||||
|  |  	struct statfs st; | ||||||
|  |  	int old_transport = 0; | ||||||
|  |   | ||||||
|  | +        (void) verb;
 | ||||||
|  | +        if (0) goto out; /* just to defeat gcc warnings */
 | ||||||
|  | +
 | ||||||
|  | +#ifdef HAVE_OPENAT
 | ||||||
|  | +        if (relay_basedir_fd >= 0) {
 | ||||||
|  | +                strncpy(buf, CTL_CHANNEL_NAME, PATH_MAX);
 | ||||||
|  | +                control_channel = openat(relay_basedir_fd, CTL_CHANNEL_NAME, O_RDWR);
 | ||||||
|  | +                dbug(2, "Opened %s (%d)\n", CTL_CHANNEL_NAME, control_channel);
 | ||||||
|  | +
 | ||||||
|  | +                /* NB: Extra real-id access check as below */
 | ||||||
|  | +                if (faccessat(relay_basedir_fd, CTL_CHANNEL_NAME, R_OK|W_OK, 0) != 0){
 | ||||||
|  | +                        close(control_channel);
 | ||||||
|  | +                        return -5;
 | ||||||
|  | +                }
 | ||||||
|  | +                if (control_channel >= 0)
 | ||||||
|  | +                        goto out; /* It's OK to bypass the [f]access[at] check below,
 | ||||||
|  | +                                     since this would only occur the *second* time 
 | ||||||
|  | +                                     staprun tries this gig, or within unprivileged stapio. */
 | ||||||
|  | +        }
 | ||||||
|  | +        /* PR14245, NB: we fall through to /sys ... /proc searching,
 | ||||||
|  | +           in case the relay_basedir_fd option wasn't given (i.e., for
 | ||||||
|  | +           early in staprun), or if errors out for some reason. */
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  |  	if (statfs("/sys/kernel/debug", &st) == 0 && (int)st.f_type == (int)DEBUGFS_MAGIC) { | ||||||
|  | -		if (sprintf_chk(buf, "/sys/kernel/debug/systemtap/%s/.cmd", name))
 | ||||||
|  | +                /* PR14245: allow subsequent operations, and if
 | ||||||
|  | +                   necessary, staprun->stapio forks, to reuse an fd for 
 | ||||||
|  | +                   directory lookups (even if some parent directories have
 | ||||||
|  | +                   perms 0700. */
 | ||||||
|  | +#ifdef HAVE_OPENAT
 | ||||||
|  | +                if (! sprintf_chk(buf, "/sys/kernel/debug/systemtap/%s", name)) {
 | ||||||
|  | +                        relay_basedir_fd = open (buf, O_DIRECTORY | O_RDONLY);
 | ||||||
|  | +                        /* If this fails, we don't much care; the
 | ||||||
|  | +                           negative return value will just keep us
 | ||||||
|  | +                           looking up by name again next time. */
 | ||||||
|  | +                        /* NB: we don't plan to close this fd, so that we can pass
 | ||||||
|  | +                           it across staprun->stapio fork/execs. */
 | ||||||
|  | +                }
 | ||||||
|  | +#endif
 | ||||||
|  | +		if (sprintf_chk(buf, "/sys/kernel/debug/systemtap/%s/%s", 
 | ||||||
|  | +                                name, CTL_CHANNEL_NAME))
 | ||||||
|  |  			return -1; | ||||||
|  |  	} else { | ||||||
|  |  		old_transport = 1; | ||||||
|  | -		if (sprintf_chk(buf, "/proc/systemtap/%s/.cmd", name))
 | ||||||
|  | +		if (sprintf_chk(buf, "/proc/systemtap/%s/%s", name, CTL_CHANNEL_NAME))
 | ||||||
|  |  			return -2; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | @@ -33,25 +74,30 @@ int init_ctl_channel(const char *name, int verb)
 | ||||||
|  |  	/* NB: Even if open() succeeded with effective-UID permissions, we | ||||||
|  |  	 * need the access() check to make sure real-UID permissions are also | ||||||
|  |  	 * sufficient.  When we run under the setuid staprun, effective and | ||||||
|  | -	 * real UID may not be the same.
 | ||||||
|  | +	 * real UID may not be the same.  Specifically, we want to prevent 
 | ||||||
|  | +         * a local stapusr from trying to attach to a different stapusr's module.
 | ||||||
|  |  	 * | ||||||
|  |  	 * The access() is done *after* open() to avoid any TOCTOU-style race | ||||||
|  |  	 * condition.  We believe it's probably safe either way, as the file | ||||||
|  |  	 * we're trying to access connot be modified by a typical user, but | ||||||
|  |  	 * better safe than sorry. | ||||||
|  |  	 */ | ||||||
|  | -	if (access(buf, R_OK|W_OK) != 0){
 | ||||||
|  | +#ifdef HAVE_OPENAT
 | ||||||
|  | +        if (control_channel >= 0 && relay_basedir_fd >= 0) {
 | ||||||
|  | +                if (faccessat (relay_basedir_fd, CTL_CHANNEL_NAME, R_OK|W_OK, 0) == 0)
 | ||||||
|  | +                        goto out;
 | ||||||
|  | +                /* else fall through */
 | ||||||
|  | +        }
 | ||||||
|  | +#endif
 | ||||||
|  | +	if (control_channel >= 0 && access(buf, R_OK|W_OK) != 0) {
 | ||||||
|  |  		close(control_channel); | ||||||
|  |  		return -5; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +out:
 | ||||||
|  |  	if (control_channel < 0) { | ||||||
|  | -		if (verb) {
 | ||||||
|  | -			if (attach_mod && errno == ENOENT)
 | ||||||
|  | -				err(_("ERROR: Can not attach. Module %s not running.\n"), name);
 | ||||||
|  | -			else
 | ||||||
|  | -				perr(_("Couldn't open control channel '%s'"), buf);
 | ||||||
|  | -		}
 | ||||||
|  | +                err(_("ERROR: Cannot attach to module %s control channel; not running?\n"), 
 | ||||||
|  | +                    name);
 | ||||||
|  |  		return -3; | ||||||
|  |  	} | ||||||
|  |  	if (set_clexec(control_channel) < 0) | ||||||
|  | diff --git a/staprun/mainloop.c b/staprun/mainloop.c
 | ||||||
|  | index b8c39d2..e68efb3 100644
 | ||||||
|  | --- a/staprun/mainloop.c
 | ||||||
|  | +++ b/staprun/mainloop.c
 | ||||||
|  | @@ -329,6 +329,8 @@ static void read_buffer_info(void)
 | ||||||
|  |    struct statfs st; | ||||||
|  |    int fd, len, ret; | ||||||
|  |   | ||||||
|  | +  /* NB: we don't have to worry about PR14245 on old_transport aka
 | ||||||
|  | +     rhel4; no HAVE_OPENAT, and thus no -F fd option. */
 | ||||||
|  |    if (!use_old_transport) | ||||||
|  |      return; | ||||||
|  |   | ||||||
|  | diff --git a/staprun/relay.c b/staprun/relay.c
 | ||||||
|  | index d5c64b7..864a8f9 100644
 | ||||||
|  | --- a/staprun/relay.c
 | ||||||
|  | +++ b/staprun/relay.c
 | ||||||
|  | @@ -7,7 +7,7 @@
 | ||||||
|  |   * Public License (GPL); either version 2, or (at your option) any | ||||||
|  |   * later version. | ||||||
|  |   * | ||||||
|  | - * Copyright (C) 2007 Red Hat Inc.
 | ||||||
|  | + * Copyright (C) 2007-2012 Red Hat Inc.
 | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  |  #include "staprun.h" | ||||||
|  | @@ -247,14 +247,15 @@ int init_relayfs(void)
 | ||||||
|  |  	relay_fd[0] = 0; | ||||||
|  |  	out_fd[0] = 0; | ||||||
|  |   | ||||||
|  | - 	if (statfs("/sys/kernel/debug", &st) == 0
 | ||||||
|  | +        if (relay_basedir_fd >= 0)
 | ||||||
|  | +                strcpy(relay_filebase, "\0");
 | ||||||
|  | + 	else if (statfs("/sys/kernel/debug", &st) == 0
 | ||||||
|  |  	    && (int) st.f_type == (int) DEBUGFS_MAGIC) { | ||||||
|  |  		if (sprintf_chk(relay_filebase, | ||||||
|  | -				"/sys/kernel/debug/systemtap/%s",
 | ||||||
|  | +				"/sys/kernel/debug/systemtap/%s/",
 | ||||||
|  |  				modname)) | ||||||
|  |  			return -1; | ||||||
|  | -	}
 | ||||||
|  | - 	else {
 | ||||||
|  | +	} else {
 | ||||||
|  |  		err("Cannot find relayfs or debugfs mount point.\n"); | ||||||
|  |  		return -1; | ||||||
|  |  	} | ||||||
|  | @@ -263,10 +264,16 @@ int init_relayfs(void)
 | ||||||
|  |  		bulkmode = 1; | ||||||
|  |   | ||||||
|  |  	for (i = 0; i < NR_CPUS; i++) { | ||||||
|  | -		if (sprintf_chk(buf, "%s/trace%d", relay_filebase, i))
 | ||||||
|  | +		if (sprintf_chk(buf, "%strace%d", relay_filebase, i))
 | ||||||
|  |  			return -1; | ||||||
|  |  		dbug(2, "attempting to open %s\n", buf); | ||||||
|  | -		relay_fd[i] = open(buf, O_RDONLY | O_NONBLOCK);
 | ||||||
|  | +                relay_fd[i] = -1;
 | ||||||
|  | +#ifdef HAVE_OPENAT
 | ||||||
|  | +                if (relay_basedir_fd >= 0)
 | ||||||
|  | +                        relay_fd[i] = openat(relay_basedir_fd, buf, O_RDONLY | O_NONBLOCK);
 | ||||||
|  | +#endif
 | ||||||
|  | +                if (relay_fd[i] < 0)
 | ||||||
|  | +                        relay_fd[i] = open(buf, O_RDONLY | O_NONBLOCK);
 | ||||||
|  |  		if (relay_fd[i] < 0 || set_clexec(relay_fd[i]) < 0) | ||||||
|  |  			break; | ||||||
|  |  	} | ||||||
|  | diff --git a/staprun/stapio.c b/staprun/stapio.c
 | ||||||
|  | index 63556e4..e8daf0e 100644
 | ||||||
|  | --- a/staprun/stapio.c
 | ||||||
|  | +++ b/staprun/stapio.c
 | ||||||
|  | @@ -15,7 +15,7 @@
 | ||||||
|  |   * You should have received a copy of the GNU General Public License | ||||||
|  |   * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |   * | ||||||
|  | - * Copyright (C) 2005-2007 Red Hat, Inc.
 | ||||||
|  | + * Copyright (C) 2005-2012 Red Hat, Inc.
 | ||||||
|  |   * | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  | @@ -33,6 +33,15 @@ int main(int argc, char **argv)
 | ||||||
|  |  	setup_signals(); | ||||||
|  |  	parse_args(argc, argv); | ||||||
|  |   | ||||||
|  | +        /* If we inherited a relay_basedir_fd, we want to keep it to ourselves -
 | ||||||
|  | +           i.e., FD_CLOEXEC the bad boy. */
 | ||||||
|  | +        if (relay_basedir_fd >= 0) {
 | ||||||
|  | +                int rc =  set_clexec(relay_basedir_fd);
 | ||||||
|  | +                if (rc) 
 | ||||||
|  | +                        exit(-1);
 | ||||||
|  | +        }
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  |  	if (buffer_size) | ||||||
|  |  		dbug(1, "Using a buffer of %u MB.\n", buffer_size); | ||||||
|  |   | ||||||
|  | diff --git a/staprun/staprun.c b/staprun/staprun.c
 | ||||||
|  | index e02a2dd..b35170b 100644
 | ||||||
|  | --- a/staprun/staprun.c
 | ||||||
|  | +++ b/staprun/staprun.c
 | ||||||
|  | @@ -204,6 +204,7 @@ static void remove_all_modules(void)
 | ||||||
|  |  	struct dirent *d; | ||||||
|  |  	DIR *moddir; | ||||||
|  |   | ||||||
|  | +        /* NB: nothing to do with PR14245 */
 | ||||||
|  |  	if (statfs("/sys/kernel/debug", &st) == 0 && (int)st.f_type == (int)DEBUGFS_MAGIC) | ||||||
|  |  		base = "/sys/kernel/debug/systemtap"; | ||||||
|  |  	else | ||||||
|  | @@ -318,7 +319,12 @@ int init_staprun(void)
 | ||||||
|  |  	rc = 0; | ||||||
|  |  	if (delete_mod) | ||||||
|  |  		exit(remove_module(modname, 1)); | ||||||
|  | -	else if (!attach_mod) {
 | ||||||
|  | +        if (attach_mod) {
 | ||||||
|  | +                /* PR14245: prime the relay_basedir_fd pump. */
 | ||||||
|  | +		rc = init_ctl_channel (modname, 0);
 | ||||||
|  | +		if (rc >= 0)
 | ||||||
|  | +		  close_ctl_channel ();
 | ||||||
|  | +        } else /* if (!attach_mod) */ {
 | ||||||
|  |  		if (need_uprobes && enable_uprobes() != 0) | ||||||
|  |  			return -1; | ||||||
|  |   | ||||||
|  | @@ -386,6 +392,17 @@ int main(int argc, char **argv)
 | ||||||
|  |   | ||||||
|  |  	parse_args(argc, argv); | ||||||
|  |   | ||||||
|  | +        /* PR14245, For security reasons, preclude "staprun -F fd".
 | ||||||
|  | +           The -F option is only for stapio, but the overzealous quest
 | ||||||
|  | +           for commonality doesn't let us express that nicer. */
 | ||||||
|  | +        if (relay_basedir_fd >= 0) {
 | ||||||
|  | +                err(_("ERROR: relay basedir -F option is invalid for staprun\n"));
 | ||||||
|  | +                exit(1);
 | ||||||
|  | +        }
 | ||||||
|  | +        /* NB: later on, some of our own code may set relay_basedir_fd, for
 | ||||||
|  | +           passing onto stapio - or for our own reuse.  That's OK.  */
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  |  	if (buffer_size) | ||||||
|  |  		dbug(2, "Using a buffer of %u MB.\n", buffer_size); | ||||||
|  |   | ||||||
|  | @@ -427,6 +444,27 @@ int main(int argc, char **argv)
 | ||||||
|  |  	if(rename_mod) | ||||||
|  |  		argv[mod_optind] = modname; | ||||||
|  |   | ||||||
|  | +        /* PR14245: pass -F fd to stapio. Unfortunately, this requires
 | ||||||
|  | +           us to extend argv[], with all the C fun that entails. */
 | ||||||
|  | +#ifdef HAVE_OPENAT
 | ||||||
|  | +        if (relay_basedir_fd >= 0) {
 | ||||||
|  | +                char ** new_argv = calloc(sizeof(char *),argc+1);
 | ||||||
|  | +                const int new_Foption_size = 10; /* -FNNNNN */
 | ||||||
|  | +                char * new_Foption = malloc(new_Foption_size);
 | ||||||
|  | +                int i;
 | ||||||
|  | +
 | ||||||
|  | +                if (new_argv && new_Foption) {
 | ||||||
|  | +                        snprintf (new_Foption, new_Foption_size, "-F%d", relay_basedir_fd);
 | ||||||
|  | +                        for (i=0; argv[i] != NULL; i++)
 | ||||||
|  | +                                new_argv[i] = argv[i];
 | ||||||
|  | +                        new_argv[i++] = new_Foption; /* overwrite the NULL */
 | ||||||
|  | +                        new_argv[i++] = NULL; /* ensconce a new NULL */
 | ||||||
|  | +
 | ||||||
|  | +                        argv = new_argv;
 | ||||||
|  | +                }
 | ||||||
|  | +        }
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  |  	/* Run stapio */ | ||||||
|  |  	if (run_as (1, getuid(), getgid(), argv[0], argv) < 0) { | ||||||
|  |  		perror(argv[0]); | ||||||
|  | diff --git a/staprun/staprun.h b/staprun/staprun.h
 | ||||||
|  | index 821b485..39cbcae 100644
 | ||||||
|  | --- a/staprun/staprun.h
 | ||||||
|  | +++ b/staprun/staprun.h
 | ||||||
|  | @@ -231,6 +231,7 @@ extern off_t fsize_max;
 | ||||||
|  |  extern int fnum_max; | ||||||
|  |  extern int remote_id; | ||||||
|  |  extern const char *remote_uri; | ||||||
|  | +extern int relay_basedir_fd;
 | ||||||
|  |   | ||||||
|  |  /* getopt variables */ | ||||||
|  |  extern char *optarg; | ||||||
|  | diff --git a/staprun/staprun_funcs.c b/staprun/staprun_funcs.c
 | ||||||
|  | index d80913d..4bc691b 100644
 | ||||||
|  | --- a/staprun/staprun_funcs.c
 | ||||||
|  | +++ b/staprun/staprun_funcs.c
 | ||||||
|  | @@ -182,6 +182,7 @@ int insert_module(
 | ||||||
|  |          if (getenv ("SYSTEMTAP_SYNC") != NULL) | ||||||
|  |                  sync(); | ||||||
|  |   | ||||||
|  | +        dbug(2,"Module %s inserted from file %s\n", modname, module_realpath);
 | ||||||
|  |  	PROBE1(staprun, insert__module, (char*)module_realpath); | ||||||
|  |  	/* Actually insert the module */ | ||||||
|  |  	ret = init_module(module_file, sbuf.st_size, opts); | ||||||
|  | @@ -311,17 +312,6 @@ rename_module(void* module_file, const __off_t st_size)
 | ||||||
|  |  #endif | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int
 | ||||||
|  | -access_debugfs(void)
 | ||||||
|  | -{
 | ||||||
|  | -	/* We need to make sure that debugfs is accessible by the real UID, or
 | ||||||
|  | -	 * else we won't be able to reach the .ctl path within. (PR14244) */
 | ||||||
|  | -	int rc = access(DEBUGFSDIR, X_OK);
 | ||||||
|  | -	if (rc < 0)
 | ||||||
|  | -		err("ERROR: no access to debugfs; try \"chmod 0755 %s\" as root\n",
 | ||||||
|  | -				DEBUGFSDIR);
 | ||||||
|  | -	return rc;
 | ||||||
|  | -}
 | ||||||
|  |   | ||||||
|  |  int mountfs(void) | ||||||
|  |  { | ||||||
|  | @@ -332,7 +322,7 @@ int mountfs(void)
 | ||||||
|  |  	/* If the debugfs dir is already mounted correctly, we're done. */ | ||||||
|  |   	if (statfs(DEBUGFSDIR, &st) == 0 | ||||||
|  |  	    && (int) st.f_type == (int) DEBUGFS_MAGIC) | ||||||
|  | -		return access_debugfs();
 | ||||||
|  | +		return 0;
 | ||||||
|  |   | ||||||
|  |  	/* If DEBUGFSDIR exists (and is a directory), try to mount | ||||||
|  |  	 * DEBUGFSDIR. */ | ||||||
|  | @@ -341,7 +331,7 @@ int mountfs(void)
 | ||||||
|  |  		/* If we can mount the debugfs dir correctly, we're done. */ | ||||||
|  |            	rc = mount ("debugfs", DEBUGFSDIR, "debugfs", 0, NULL); | ||||||
|  |  		if (rc == 0) | ||||||
|  | -			return access_debugfs();
 | ||||||
|  | +			return 0;
 | ||||||
|  |  		/* If we got ENODEV, that means that debugfs isn't | ||||||
|  |  		 * supported, so we'll need try try relayfs.  If we | ||||||
|  |  		 * didn't get ENODEV, we got a real error. */ | ||||||
| @ -33,7 +33,7 @@ | |||||||
| 
 | 
 | ||||||
| Name: systemtap | Name: systemtap | ||||||
| Version: 2.0 | Version: 2.0 | ||||||
| Release: 4%{?dist} | Release: 5%{?dist} | ||||||
| # for version, see also configure.ac | # for version, see also configure.ac | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -111,6 +111,10 @@ BuildRequires: /usr/share/publican/Common_Content/%{publican_brand}/defaults.cfg | |||||||
| # fix minor changes for dyninst 8.0 final | # fix minor changes for dyninst 8.0 final | ||||||
| Patch2: systemtap-2.0-dyninst-fixes.patch | Patch2: systemtap-2.0-dyninst-fixes.patch | ||||||
| 
 | 
 | ||||||
|  | # fixes for kernel 3.7, PR14245 and PR14712 | ||||||
|  | Patch3: systemtap-2.0-missing-VM_EXECUTABLE.patch | ||||||
|  | Patch4: systemtap-2.0-mode-0700-debugfs.patch | ||||||
|  | 
 | ||||||
| # Install requirements | # Install requirements | ||||||
| Requires: systemtap-client = %{version}-%{release} | Requires: systemtap-client = %{version}-%{release} | ||||||
| Requires: systemtap-devel = %{version}-%{release} | Requires: systemtap-devel = %{version}-%{release} | ||||||
| @ -277,6 +281,9 @@ cd .. | |||||||
| 
 | 
 | ||||||
| %patch2 -p1 | %patch2 -p1 | ||||||
| 
 | 
 | ||||||
|  | %patch3 -p1 | ||||||
|  | %patch4 -p1 | ||||||
|  | 
 | ||||||
| %build | %build | ||||||
| 
 | 
 | ||||||
| %if %{with_bundled_elfutils} | %if %{with_bundled_elfutils} | ||||||
| @ -621,6 +628,9 @@ exit 0 | |||||||
| # ------------------------------------------------------------------------ | # ------------------------------------------------------------------------ | ||||||
| 
 | 
 | ||||||
| %changelog | %changelog | ||||||
|  | * Wed Jan 16 2013 Josh Stone <jistone@redhat.com> 2.0-5 | ||||||
|  | - Backport fixes to work with kernel 3.7 | ||||||
|  | 
 | ||||||
| * Mon Nov 19 2012 Josh Stone <jistone@redhat.com> 2.0-4 | * Mon Nov 19 2012 Josh Stone <jistone@redhat.com> 2.0-4 | ||||||
| - Rebuild for the final dyninst 8.0. | - Rebuild for the final dyninst 8.0. | ||||||
| - As with rawhide, disable docs due to bz864730 | - As with rawhide, disable docs due to bz864730 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user