diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2012-01-21 13:26:26 -0500 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2012-01-24 19:37:55 -0500 |
commit | 6e9d5164153ad6539edd31e7afb02a3e79124cad (patch) | |
tree | ce6cb28dca49f68cc6236dc70a71ecf93593159f | |
parent | f05e53a7fbb28c951c0c8cf3963fa8019ae1d4d3 (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.c | 94 | ||||
-rw-r--r-- | include/linux/sysctl.h | 3 |
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 | */ |
937 | struct ctl_table_header *__register_sysctl_paths( | 937 | struct 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 | ||
1049 | static 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 | */ | ||
1074 | struct 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); | ||
1094 | out: | ||
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, | |||
1073 | extern void retire_sysctl_set(struct ctl_table_set *set); | 1073 | extern void retire_sysctl_set(struct ctl_table_set *set); |
1074 | 1074 | ||
1075 | void register_sysctl_root(struct ctl_table_root *root); | 1075 | void register_sysctl_root(struct ctl_table_root *root); |
1076 | struct ctl_table_header *__register_sysctl_table( | ||
1077 | struct ctl_table_root *root, struct nsproxy *namespaces, | ||
1078 | const char *path, struct ctl_table *table); | ||
1076 | struct ctl_table_header *__register_sysctl_paths( | 1079 | struct 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); |