aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-01-21 13:26:26 -0500
committerEric W. Biederman <ebiederm@xmission.com>2012-01-24 19:37:55 -0500
commit6e9d5164153ad6539edd31e7afb02a3e79124cad (patch)
treece6cb28dca49f68cc6236dc70a71ecf93593159f
parentf05e53a7fbb28c951c0c8cf3963fa8019ae1d4d3 (diff)
sysctl: Add support for register sysctl tables with a normal cstring path.
Make __register_sysctl_table the core sysctl registration operation and make it take a char * string as path. Now that binary paths have been banished into the real of backwards compatibility in kernel/binary_sysctl.c where they can be safely ignored there is no longer a need to use struct ctl_path to represent path names when registering ctl_tables. Start the transition to using normal char * strings to represent pathnames when registering sysctl tables. Normal strings are easier to deal with both in the internal sysctl implementation and for programmers registering sysctl tables. __register_sysctl_paths is turned into a backwards compatibility wrapper that converts a ctl_path array into a normal char * string. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
-rw-r--r--fs/proc/proc_sysctl.c94
-rw-r--r--include/linux/sysctl.h3
2 files changed, 87 insertions, 10 deletions
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index bcf60fb8dce5..5704ff0e889f 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -882,7 +882,7 @@ static int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *tabl
882#endif /* CONFIG_SYSCTL_SYSCALL_CHECK */ 882#endif /* CONFIG_SYSCTL_SYSCALL_CHECK */
883 883
884/** 884/**
885 * __register_sysctl_paths - register a sysctl hierarchy 885 * __register_sysctl_table - register a sysctl table
886 * @root: List of sysctl headers to register on 886 * @root: List of sysctl headers to register on
887 * @namespaces: Data to compute which lists of sysctl entries are visible 887 * @namespaces: Data to compute which lists of sysctl entries are visible
888 * @path: The path to the directory the sysctl table is in. 888 * @path: The path to the directory the sysctl table is in.
@@ -934,21 +934,34 @@ static int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *tabl
934 * This routine returns %NULL on a failure to register, and a pointer 934 * This routine returns %NULL on a failure to register, and a pointer
935 * to the table header on success. 935 * to the table header on success.
936 */ 936 */
937struct ctl_table_header *__register_sysctl_paths( 937struct ctl_table_header *__register_sysctl_table(
938 struct ctl_table_root *root, 938 struct ctl_table_root *root,
939 struct nsproxy *namespaces, 939 struct nsproxy *namespaces,
940 const struct ctl_path *path, struct ctl_table *table) 940 const char *path, struct ctl_table *table)
941{ 941{
942 struct ctl_table_header *header; 942 struct ctl_table_header *header;
943 struct ctl_table *new, **prevp; 943 struct ctl_table *new, **prevp;
944 unsigned int n, npath; 944 const char *name, *nextname;
945 unsigned int npath = 0;
945 struct ctl_table_set *set; 946 struct ctl_table_set *set;
946 size_t path_bytes = 0; 947 size_t path_bytes = 0;
947 char *new_name; 948 char *new_name;
948 949
949 /* Count the path components */ 950 /* Count the path components */
950 for (npath = 0; path[npath].procname; ++npath) 951 for (name = path; name; name = nextname) {
951 path_bytes += strlen(path[npath].procname) + 1; 952 int namelen;
953 nextname = strchr(name, '/');
954 if (nextname) {
955 namelen = nextname - name;
956 nextname++;
957 } else {
958 namelen = strlen(name);
959 }
960 if (namelen == 0)
961 continue;
962 path_bytes += namelen + 1;
963 npath++;
964 }
952 965
953 /* 966 /*
954 * For each path component, allocate a 2-element ctl_table array. 967 * For each path component, allocate a 2-element ctl_table array.
@@ -968,9 +981,20 @@ struct ctl_table_header *__register_sysctl_paths(
968 981
969 /* Now connect the dots */ 982 /* Now connect the dots */
970 prevp = &header->ctl_table; 983 prevp = &header->ctl_table;
971 for (n = 0; n < npath; ++n, ++path) { 984 for (name = path; name; name = nextname) {
972 /* Copy the procname */ 985 int namelen;
973 strcpy(new_name, path->procname); 986 nextname = strchr(name, '/');
987 if (nextname) {
988 namelen = nextname - name;
989 nextname++;
990 } else {
991 namelen = strlen(name);
992 }
993 if (namelen == 0)
994 continue;
995 memcpy(new_name, name, namelen);
996 new_name[namelen] = '\0';
997
974 new->procname = new_name; 998 new->procname = new_name;
975 new->mode = 0555; 999 new->mode = 0555;
976 1000
@@ -978,7 +1002,7 @@ struct ctl_table_header *__register_sysctl_paths(
978 prevp = &new->child; 1002 prevp = &new->child;
979 1003
980 new += 2; 1004 new += 2;
981 new_name += strlen(new_name) + 1; 1005 new_name += namelen + 1;
982 } 1006 }
983 *prevp = table; 1007 *prevp = table;
984 header->ctl_table_arg = table; 1008 header->ctl_table_arg = table;
@@ -1022,6 +1046,56 @@ struct ctl_table_header *__register_sysctl_paths(
1022 return header; 1046 return header;
1023} 1047}
1024 1048
1049static char *append_path(const char *path, char *pos, const char *name)
1050{
1051 int namelen;
1052 namelen = strlen(name);
1053 if (((pos - path) + namelen + 2) >= PATH_MAX)
1054 return NULL;
1055 memcpy(pos, name, namelen);
1056 pos[namelen] = '/';
1057 pos[namelen + 1] = '\0';
1058 pos += namelen + 1;
1059 return pos;
1060}
1061
1062/**
1063 * __register_sysctl_paths - register a sysctl table hierarchy
1064 * @root: List of sysctl headers to register on
1065 * @namespaces: Data to compute which lists of sysctl entries are visible
1066 * @path: The path to the directory the sysctl table is in.
1067 * @table: the top-level table structure
1068 *
1069 * Register a sysctl table hierarchy. @table should be a filled in ctl_table
1070 * array. A completely 0 filled entry terminates the table.
1071 *
1072 * See __register_sysctl_table for more details.
1073 */
1074struct ctl_table_header *__register_sysctl_paths(
1075 struct ctl_table_root *root,
1076 struct nsproxy *namespaces,
1077 const struct ctl_path *path, struct ctl_table *table)
1078{
1079 struct ctl_table_header *header = NULL;
1080 const struct ctl_path *component;
1081 char *new_path, *pos;
1082
1083 pos = new_path = kmalloc(PATH_MAX, GFP_KERNEL);
1084 if (!new_path)
1085 return NULL;
1086
1087 pos[0] = '\0';
1088 for (component = path; component->procname; component++) {
1089 pos = append_path(new_path, pos, component->procname);
1090 if (!pos)
1091 goto out;
1092 }
1093 header = __register_sysctl_table(root, namespaces, new_path, table);
1094out:
1095 kfree(new_path);
1096 return header;
1097}
1098
1025/** 1099/**
1026 * register_sysctl_table_path - register a sysctl table hierarchy 1100 * register_sysctl_table_path - register a sysctl table hierarchy
1027 * @path: The path to the directory the sysctl table is in. 1101 * @path: The path to the directory the sysctl table is in.
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 43c36acdb628..a514e0f6056d 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -1073,6 +1073,9 @@ extern void setup_sysctl_set(struct ctl_table_set *p,
1073extern void retire_sysctl_set(struct ctl_table_set *set); 1073extern void retire_sysctl_set(struct ctl_table_set *set);
1074 1074
1075void register_sysctl_root(struct ctl_table_root *root); 1075void register_sysctl_root(struct ctl_table_root *root);
1076struct ctl_table_header *__register_sysctl_table(
1077 struct ctl_table_root *root, struct nsproxy *namespaces,
1078 const char *path, struct ctl_table *table);
1076struct ctl_table_header *__register_sysctl_paths( 1079struct ctl_table_header *__register_sysctl_paths(
1077 struct ctl_table_root *root, struct nsproxy *namespaces, 1080 struct ctl_table_root *root, struct nsproxy *namespaces,
1078 const struct ctl_path *path, struct ctl_table *table); 1081 const struct ctl_path *path, struct ctl_table *table);