Re: [PATCH] kernel/sysctl.c: If "count" including the terminating byte '\0' the write system call should retrun success.

From: Sean Fu
Date: Mon Aug 24 2015 - 23:13:13 EST


Call path is "proc_dointvec-->do_proc_dointvec-->__do_proc_dointvec-->proc_get_long".
file: kernel/sysctl.c
function: proc_get_long
...
1927 if (len < *size && perm_tr_len && !memchr(perm_tr, *p,
perm_tr_len)) //this line should accept two bytes
"1\0".
1928 return -EINVAL;
...


The latest upstream kernel is also tested, and it is same as 3.16.7 kernel.

3.16.7 kernel:
sean@linux-dunz:~/work/suse_lab/proc_test> cat /proc/version
Linux version 3.16.7-7-desktop (geeko@buildhost) (gcc version 4.8.3
20140627 [gcc-4_8-branch revision 212064] (SUSE Linux) ) #1 SMP
PREEMPT Wed Dec 17 18:00:44 UTC 2014 (762f27a)
sean@linux-dunz:~/work/suse_lab/proc_test> gcc ./proc_test.c -o proc_test
sean@linux-dunz:~/work/suse_lab/proc_test> sudo ./proc_test enp0s25
Input: ./proc_test, enp0s25
file is: /proc/sys/net/ipv4/conf/enp0s25/rp_filter.
open /proc/sys/net/ipv4/conf/enp0s25/rp_filter ok, fd=3
write 3: len=-1, errno=22, Invalid argument

2.6.16.60 kernel:
linux-8lij:~ # gcc ./proc_test.c -o ./proc_test
linux-8lij:~ # cat /proc/version
Linux version 2.6.16.60-0.83.2-bigsmp (geeko@buildhost) (gcc version
4.1.2 20070115 (SUSE Linux)) #1 SMP Fri Sep 2 13:49:16 UTC 2011
linux-8lij:~ # gcc ./proc_test.c -o ./proc_test
linux-8lij:~ # ./proc_test eth7
Input: ./proc_test, eth7
file is: /proc/sys/net/ipv4/conf/eth7/rp_filter.
open /proc/sys/net/ipv4/conf/eth7/rp_filter ok, fd=3
write 3: len=1, errno=0, Success

On Tue, Aug 25, 2015 at 8:57 AM, Sean Fu <fxinrong@xxxxxxxxx> wrote:
> An application from HuaWei which works fine on 2.6 encounters this
> issue on 3.0 or later kernel.
>
> Test code:
>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <unistd.h>
> #include <stdio.h>
> #include <string.h>
> #include <errno.h>
>
> #define MAXLEN (100)
>
> int main(int argc, char** argv)
> {
> int fd = 0;
> int len = 0;
> char pathname[MAXLEN] = {0};
> char buf[2] = {0};
> int ret = 0xF;
> int value = 0xF;
>
> if (argc < 2)
> {
> printf("Input param error, less 2 param: %s, %s.\n",
> argv[0], argv[1]);
> return 1;
> }
>
> printf("Input: %s, %s \n", argv[0], argv[1]);
>
> ret = sprintf(pathname,
> "/proc/sys/net/ipv4/conf/%s/rp_filter", argv[1]);
> if (ret < 0)
> printf("sprintf error, errno %d, %s\n", errno, strerror(errno));
> printf("file is: %s. \n", pathname);
>
> fd = open(pathname, O_RDWR, S_IRUSR);
> if (fd <=0 )
> {
> printf("open %s failed, errno=%d, %s.\n", pathname,
> errno, strerror(errno));
> return 1;
> }
> printf("open %s ok, fd=%d\n", pathname, fd);
>
> len = write(fd, "0\0", 2);
> printf("write %d: len=%d, errno=%d, %s\n", fd, len, errno,
> strerror(errno));
>
> close(fd);
> return 0;
> }
>
> On Tue, Aug 25, 2015 at 12:59 AM, Steven Rostedt <rostedt@xxxxxxxxxxx> wrote:
>> On Mon, 24 Aug 2015 16:56:13 +0800
>> Sean Fu <fxinrong@xxxxxxxxx> wrote:
>>
>>> when the input argument "count" including the terminating byte "\0",
>>> The write system call return EINVAL on proc file.
>>> But it return success on regular file.
>>>
>>> E.g. Writting two bytes ("1\0") to "/proc/sys/net/ipv4/conf/eth0/rp_filter".
>>> write(fd, "1\0", 2) return EINVAL.
>>
>> And what would do that? What tool broke because of this?
>>
>> echo 1 > /proc/sys/net/ipv4/conf/eth0/rp_filter
>>
>> works just fine. strlen("string") would not include the nul character.
>> The only thing I could think of would be a sizeof(str), but then that
>> would include someone hardcoding an integer in a string, like:
>>
>> char val[] = "1"
>>
>> write(fd, val, sizeof(val));
>>
>> Again, what tool does that?
>>
>> If there is a tool out in the wild that use to work on 2.6 (and was
>> running on 2.6 then, and not something that was created after that
>> change), then we can consider this fix.
>>
>> -- Steve
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/