lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20160825152110.25663-4-dsafonov@virtuozzo.com>
Date:   Thu, 25 Aug 2016 18:21:10 +0300
From:   Dmitry Safonov <dsafonov@...tuozzo.com>
To:     <linux-kernel@...r.kernel.org>, <mingo@...hat.com>
CC:     <luto@...capital.net>, <tglx@...utronix.de>, <hpa@...or.com>,
        <x86@...nel.org>, <0x7f454c46@...il.com>, <oleg@...hat.com>,
        <rostedt@...dmis.org>, <viro@...iv.linux.org.uk>,
        Dmitry Safonov <dsafonov@...tuozzo.com>
Subject: [RFC 3/3] uprobe: add vdso support

For RFC, this patch is full of hacks:
- non-generic vdso_mnt -- it will not built on !x86_64
- used externs in trace_uprobe.c, rather than clean header-includes

This patch converts vdsofs from lookup-less, renames vdso file name
to just "64". It also adds support to uprobe_events for setting uprobe
to vdso image file.

One can set vdso uprobe now like this:
echo 'p:gettimeofday :vdso:/64:0xc50' >> uprobe_events

Signed-off-by: Dmitry Safonov <dsafonov@...tuozzo.com>
---
 arch/x86/entry/vdso/vma.c   | 28 ++++++++++++++-------------
 kernel/trace/trace_uprobe.c | 46 +++++++++++++++++++++++++++++++++++++--------
 2 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index e83830e422ae..9e966b649028 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -39,7 +39,7 @@ void __init init_vdso_image(const struct vdso_image *image)
 						image->alt_len));
 }
 
-static struct vfsmount *vdso_mnt;
+struct vfsmount *vdso_mnt;
 struct file *vdso_file_64;
 
 struct linux_binprm;
@@ -401,38 +401,40 @@ static __init struct file *init_vdso_file(const struct vdso_image *vdso_image,
 					const char *name)
 {
 	struct super_block *sb;
-	struct qstr name_str;
 	struct inode *inode;
 	struct path path;
 	struct file *res;
+	int ret;
 
 	if (IS_ERR(vdso_mnt))
 		return ERR_CAST(vdso_mnt);
 	sb = vdso_mnt->mnt_sb;
 
-	name_str.hash = 0;
-	name_str.len = strlen(name);
-	name_str.name = name;
-
 	res = ERR_PTR(-ENOMEM);
 	path.mnt = mntget(vdso_mnt);
-	path.dentry = d_alloc_pseudo(sb, &name_str);
-	if (!path.dentry)
+	path.dentry = d_alloc_name(vdso_mnt->mnt_root, name);
+	if (!path.dentry) {
+		pr_err("Failed to allocate dentry for %s vdso file\n", name);
 		goto put_path;
+	}
 	d_set_d_op(path.dentry, &vdso_dops);
 
 	res = ERR_PTR(-ENOSPC);
 	inode = ramfs_get_inode(sb, NULL, S_IFREG | S_IRUGO | S_IXUGO, 0);
-	if (!inode)
+	if (!inode) {
+		pr_err("Failed to get inode for %s vdso file\n", name);
 		goto put_path;
+	}
 
 	inode->i_flags |= S_PRIVATE;
-	d_instantiate(path.dentry, inode);
+	d_add(path.dentry, inode);
 	inode->i_size = vdso_image->size;
 
-	res = ERR_PTR(add_vdso_pages_to_page_cache(vdso_image, inode));
-	if (IS_ERR(res))
+	ret = add_vdso_pages_to_page_cache(vdso_image, inode);
+	if (ret) {
+		pr_err("Failed to put %s pages in page cache: %d\n", name, ret);
 		goto put_path;
+	}
 
 	res = alloc_file(&path, FMODE_READ, &ramfs_file_operations);
 	if (!IS_ERR(res))
@@ -475,7 +477,7 @@ static int __init init_vdso(void)
 
 	BUG_ON(init_vdso_fs());
 
-	vdso_file_64 = init_vdso_file(&vdso_image_64, "vdso_image_64");
+	vdso_file_64 = init_vdso_file(&vdso_image_64, "64");
 	BUG_ON(IS_ERR(vdso_file_64));
 
 	/* notifier priority > KVM */
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index a74f2d9ff379..3d4dc6c6ddd9 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -23,6 +23,7 @@
 #include <linux/uprobes.h>
 #include <linux/namei.h>
 #include <linux/string.h>
+#include <linux/mount.h>
 
 #include "trace_probe.h"
 
@@ -352,6 +353,9 @@ end:
  *
  *  - Remove uprobe: -:[GRP/]EVENT
  */
+extern struct vfsmount *vdso_mnt;
+extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
+			   const char *, unsigned int, struct path *);
 static int create_trace_uprobe(int argc, char **argv)
 {
 	struct trace_uprobe *tu;
@@ -427,15 +431,41 @@ static int create_trace_uprobe(int argc, char **argv)
 		pr_info("Probe point is not specified.\n");
 		return -EINVAL;
 	}
-	arg = strchr(argv[1], ':');
-	if (!arg) {
-		ret = -EINVAL;
-		goto fail_address_parse;
-	}
+	if (argv[1][0] == ':') {
+		arg = strchr(&argv[1][1], ':');
+		if (!arg) {
+			ret = -EINVAL;
+			goto fail_address_parse;
+		}
+		*arg++ = '\0';
+		if (strcmp(&argv[1][1], "vdso")) {
+			ret = -EINVAL;
+			goto fail_address_parse;
+		}
+		filename = arg;
+		arg = strchr(filename, ':');
+		if (!filename) {
+			ret = -EINVAL;
+			goto fail_address_parse;
+		}
+		*arg++ = '\0';
+		if (!vdso_mnt) {
+			ret = -ENODEV;
+			goto fail_address_parse;
+		}
+		ret = vfs_path_lookup(vdso_mnt->mnt_root, vdso_mnt,
+				filename, LOOKUP_FOLLOW, &path);
+	} else {
+		arg = strchr(argv[1], ':');
+		if (!arg) {
+			ret = -EINVAL;
+			goto fail_address_parse;
+		}
 
-	*arg++ = '\0';
-	filename = argv[1];
-	ret = kern_path(filename, LOOKUP_FOLLOW, &path);
+		*arg++ = '\0';
+		filename = argv[1];
+		ret = kern_path(filename, LOOKUP_FOLLOW, &path);
+	}
 	if (ret)
 		goto fail_address_parse;
 
-- 
2.9.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ