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-next>] [day] [month] [year] [list]
Date:	Fri, 28 Sep 2007 10:16:01 -0700
From:	Ken Schmidt <kenneth.schmidt@....gov>
To:	viro@...iv.linux.org.uk
Cc:	linux-kernel@...r.kernel.org, kenneth.schmidt@....gov
Subject: [patch 01/02] vfs: variant symlinks

Variant symlinks add the ability to embed variables in to the contents of symbolic links so their targets can change based on outside sources (user environment, uts, filesystems, etc.)

Signed-off-by: Ken Schmidt <kenneth.schmidt@....gov>
---
diff -urN linux-2.6.22.5.orig/include/linux/variant.h linux-2.6.22.5/include/linux/variant.h
--- linux-2.6.22.5.orig/include/linux/variant.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.22.5/include/linux/variant.h	2007-08-28 09:35:40.000000000 -0700
@@ -0,0 +1,10 @@
+#ifndef _LINUX_VARIANT_H
+#define _LINUX_VARIANT_H
+
+int variant_func_register(int ( *variant_func)(const char *, int, char *, int), int priority, char *name);
+void variant_func_unregister(int id);
+int do_variant_lookup(const char *path, char **newpath);
+
+extern int variant_links_enabled;
+
+#endif /* _LINUX_VARIANT_H */
diff -urN linux-2.6.22.5.orig/fs/Kconfig linux-2.6.22.5/fs/Kconfig
--- linux-2.6.22.5.orig/fs/Kconfig	2007-08-22 16:23:54.000000000 -0700
+++ linux-2.6.22.5/fs/Kconfig	2007-09-23 09:16:04.000000000 -0700
@@ -524,6 +524,14 @@
 
 	  If unsure, say Y.
 
+config VARIANT
+	bool "Variant symlink support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  If you say Y here, all filesystems will have the ability to
+	  dynamically redirect their symbolic link targets based on embedded
+	  variables. If unsure, say N
+
 config QUOTA
 	bool "Quota support"
 	help
diff -urN linux-2.6.22.5.orig/fs/Makefile linux-2.6.22.5/fs/Makefile
--- linux-2.6.22.5.orig/fs/Makefile	2007-08-22 16:23:54.000000000 -0700
+++ linux-2.6.22.5/fs/Makefile	2007-09-23 09:15:25.000000000 -0700
@@ -63,6 +63,8 @@
 
 obj-$(CONFIG_PROFILING)		+= dcookies.o
 obj-$(CONFIG_DLM)		+= dlm/
+
+obj-$(CONFIG_VARIANT)		+= variant/
  
 # Do not add any filesystems before this line
 obj-$(CONFIG_REISERFS_FS)	+= reiserfs/
diff -urN linux-2.6.22.5.orig/fs/variant/Makefile linux-2.6.22.5/fs/variant/Makefile
--- linux-2.6.22.5.orig/fs/variant/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.22.5/fs/variant/Makefile	2007-09-23 09:17:04.000000000 -0700
@@ -0,0 +1,5 @@
+#
+# Makefile for the variant symlinks
+#
+
+obj-$(CONFIG_VARIANT) += variant.o
diff -urN linux-2.6.22.5.orig/fs/namei.c linux-2.6.22.5/fs/namei.c
--- linux-2.6.22.5.orig/fs/namei.c	2007-08-22 16:23:54.000000000 -0700
+++ linux-2.6.22.5/fs/namei.c	2007-09-23 07:15:52.000000000 -0700
@@ -31,6 +31,7 @@
 #include <linux/file.h>
 #include <linux/fcntl.h>
 #include <linux/namei.h>
+#include <linux/variant.h>
 #include <asm/namei.h>
 #include <asm/uaccess.h>
 
@@ -539,10 +540,25 @@
 static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
 {
 	int res = 0;
+#ifdef CONFIG_VARIANT
+	char *newlink = NULL;
+	int err;
+#endif
 	char *name;
 	if (IS_ERR(link))
 		goto fail;
 
+#ifdef CONFIG_VARIANT
+	if (variant_links_enabled && strchr(link, '$')) {
+		err = do_variant_lookup(link, &newlink);
+		if (err) {
+			path_release(nd);
+			return err;
+		}
+		link = newlink;
+	}
+#endif
+
 	if (*link == '/') {
 		path_release(nd);
 		if (!walk_init_root(link, nd))
@@ -551,6 +565,11 @@
 	}
 	res = link_path_walk(link, nd);
 out:
+#ifdef CONFIG_VARIANT
+	if (newlink == link)
+		kfree(newlink);
+#endif
+
 	if (nd->depth || res || nd->last_type!=LAST_NORM)
 		return res;
 	/*
--- linux-2.6.22.5.unpacked/fs/variant/variant.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.22.5/fs/variant/variant.c	2007-09-24 04:26:57.000000000 -0700
@@ -0,0 +1,183 @@
+/*
+ *   Copyright (C) Pacific Northwest National Laboratory., 2007
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *   written by Kenneth P Schmidt (kenneth.schmidt <at> pnl.gov) for the
+ *   Department of Energy
+ */
+
+#include<linux/kernel.h>
+#include<linux/slab.h>
+#include<linux/string.h>
+#include<linux/limits.h>
+#include<linux/rwsem.h>
+#include<linux/module.h>
+#include<linux/variant.h>
+
+struct variant_func_module {
+	int id;
+
+	char *name;	/* name for possible reporting to user space (sysfs) */
+
+	/* priority lists the order for variable lookups. 0 - highest priority*/
+	int priority;
+
+	/*
+	 * the callback function for each registered module.
+	 * key points to the key in the original path
+	 * keylen is the length of the key
+	 * dest is the buffer to copy directly into
+	 * destlen is the length allowed to write into the dest buffer
+	 */
+	int ( *variant_lookup_func)(const char *key, int keylen, char *dest, int destlen);
+
+	struct list_head list;
+};
+
+static DECLARE_RWSEM(variant_module_rwsem);
+static LIST_HEAD(variant_func_list);
+static int variant_func_uniq;
+
+int variant_links_enabled = 1;
+
+int variant_func_register(int ( *variant_func)(const char *, int, char *, int), int priority, char *name)
+{
+	int retval;
+	int inserted = 0;
+	struct variant_func_module *new_module, *cur_module;
+	struct list_head *cur;
+
+	down_write(&variant_module_rwsem);
+	new_module = (struct variant_func_module *)kmalloc(
+					sizeof(struct variant_func_module),
+					GFP_KERNEL);
+	if (new_module) {
+		new_module->variant_lookup_func = variant_func;
+		retval = (new_module->id) = ++variant_func_uniq;
+		new_module->priority = priority;
+		new_module->name = (char *)kmalloc(strlen(name)+1, GFP_KERNEL);
+		strcpy(new_module->name, name);
+		list_for_each(cur, &variant_func_list) {
+			cur_module = list_entry(cur, struct variant_func_module, list);
+			if (cur_module->priority < priority) {
+				list_add_tail(&new_module->list, cur);
+				inserted = 1;
+			}
+		}
+		if (!inserted)
+			list_add_tail(&new_module->list, &variant_func_list);
+	} else {
+		retval = -1;
+	}
+	up_write(&variant_module_rwsem);
+	return retval;
+}
+EXPORT_SYMBOL(variant_func_register);
+
+void variant_func_unregister(int id)
+{
+	struct list_head *cur, *tmp;
+
+	down_write(&variant_module_rwsem);
+	list_for_each_safe(cur, tmp, &variant_func_list) {
+		if (list_entry(cur, struct variant_func_module, list)->id == id) {
+			list_del(cur);
+			kfree(list_entry(cur, struct variant_func_module, list));
+		}
+	}
+	up_write(&variant_module_rwsem);
+}
+EXPORT_SYMBOL(variant_func_unregister);
+
+static int variant_var_lookup(const char *key, int keylen, char *dest, int destlen)
+{
+	struct list_head *cur;
+	int modsize = 0;
+	struct variant_func_module *cur_module;
+
+	if (keylen == 0)
+		return 0;
+
+	down_read(&variant_module_rwsem);
+	list_for_each(cur, &variant_func_list) {
+		/*
+		 * call each modules' lookup function
+		 * until one of them returns something
+		 */
+		cur_module = list_entry(cur, struct variant_func_module, list);
+		modsize = (*(cur_module)->variant_lookup_func)(key, keylen, dest, destlen);
+		if (modsize != 0)
+			break;
+	}
+	up_read(&variant_module_rwsem);
+	return modsize;
+}
+
+/*make sure to free the returned string*/
+int do_variant_lookup(const char *path, char **newpath)
+{
+	const char *beg, *end, *cur;
+	char *tmppath;
+	int varsize;
+
+	*newpath = (char *)kmalloc(PATH_MAX, GFP_KERNEL);
+	if (*newpath == NULL) {
+		return -ENOMEM;
+	}
+
+	cur = beg = path;
+	tmppath = *newpath;
+	while ((cur = strchr(cur, '$'))) {
+		if ((cur[1] == '{') && (end = strchr(cur+2, '}'))) {
+
+			/*
+			 * Copy everything before the variable into our new
+			 * buffer, making sure we didn't already overrun it
+			 */
+			varsize = cur - beg;
+			if (varsize + (tmppath - *newpath) > PATH_MAX) {
+				kfree(*newpath);
+				return -ENAMETOOLONG;
+			}
+			strncpy(tmppath, beg, varsize);
+			tmppath += varsize;
+
+			varsize = variant_var_lookup(cur + 2, end - cur - 2, tmppath, PATH_MAX - (tmppath - *newpath));
+			/*
+			 * if zero was returned, then there was no variable
+			 * replacement. Leave the variable in the path
+			 */
+			if (varsize == 0) {
+				varsize = end - cur + 1;
+				if (varsize + (tmppath - *newpath) > PATH_MAX) {
+					kfree(*newpath);
+					return -ENAMETOOLONG;
+				}
+				strncpy(tmppath, cur, varsize);
+			}
+			tmppath += varsize;
+
+			cur = beg = end;
+			beg++;
+		}
+		cur++;
+	}
+	/* copy in the rest of the path */
+	strncpy(tmppath, beg, PATH_MAX - (tmppath - *newpath));
+	(*newpath)[PATH_MAX - 1] = '\0';
+	return 0;
+}
+
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ