Hello, I have several questions about sysctl(). Q1: Why does sysctl_string() return 0 when it succeed? The sysctl_string() do r/w operations, so we needn't to proceed with automatic r/w when sysctl_string() is called as a strategy routine (i.e. table->strategy). http://lxr.linux.no/source/kernel/sysctl.c#L1087 Q2: If Q1 is not a bug, then I have Q2. Why not terminate with '\0' if doing string copy operation at http://lxr.linux.no/source/kernel/sysctl.c#L1115 ? At least, as with table->strategy == &sysctl_string , '\0' should be always added after string copy operation. For example, /proc/sys/kernel/hostname uses sysctl_string() for strategy routine. http://lxr.linux.no/source/kernel/sysctl.c#L249 Since sysctl_string() returns 0, do_sysctl_strategy() continues and proceeds with automatic r/w. But since automatic r/w doesn't set trailing '\0', table->data doesn't end with '\0' if newlen > table->maxlen. This makes system_utsname.nodename not null-terminated. Q3: The parse_table() call table->strategy() if table->child != NULL && table->strategy != NULL . http://lxr.linux.no/source/kernel/sysctl.c#L1049 Can such table (table->child != NULL && table->strategy != NULL) exist? If such table can exist, table->strategy() is called without ctl_perm(table, r/w) checks, allowing non-root process read/write that table. We need to call ctl_perm() before calling table->strategy(), aren't we? If such table can't exist, we can remove "if (table->strategy) { ... }" block (from http://lxr.linux.no/source/kernel/sysctl.c#L1049 to http://lxr.linux.no/source/kernel/sysctl.c#L1056 ), aren't we? Q4: do_sysctl() gets lock_kernel() but no uts_sem lock ( http://lxr.linux.no/source/kernel/sysctl.c#L1001 ), and sys_sethostname() gets uts_sem lock but no lock_kernel() ( http://lxr.linux.no/source/kernel/sys.c#L1376 ). This allows one process update hostname via sys_sysctl() and the other process update hostname via sys_sethostname() at the same time. As with hostname, the race condition probably won't crash the system. But there MAY be more sysctl-accessible variables that can produce race condition. Why not review all sysctl-accessible variables? ----- demo code for Q2 start ----- #include <stdio.h> #include <string.h> #include <unistd.h> #include <linux/unistd.h> #include <linux/types.h> #include <linux/sysctl.h> #include <errno.h> _syscall1(int, _sysctl, struct __sysctl_args *, args); static int sysctl(int *name, int nlen, void *oldval, size_t *oldlenp, void *newval, size_t newlen) { struct __sysctl_args args={name,nlen,oldval,oldlenp,newval,newlen}; return _sysctl(&args); } int main(int argc, char *argv[]) { int name[] = { CTL_KERN, KERN_NODENAME }; static char buffer[128]; memset(buffer, 0, sizeof(buffer)); snprintf(buffer, sizeof(buffer) - 1, "12345678901234567890123456789012345678901234567890123456789012345"); if (sysctl(name, 2, NULL, 0, buffer, sizeof(buffer))) perror("sysctl"); else printf("hostname was set via sysctl()\n"); return 0; } ----- demo code for Q2 end ----- Regards... -- Tetsuo Handa (Sorry, I can't choose us-ascii charset, for I'm posting from webmail.) -- Kernelnewbies: Help each other learn about the Linux kernel. Archive: http://mail.nl.linux.org/kernelnewbies/ FAQ: http://kernelnewbies.org/faq/