How can I get argv from struct linux_binprm?
. If you want to get the full command line before the binary loader executing in do_execve_common(), you can try following:
there is one argument *argv in the function do_execve_common() parameter table, why bother to get the argv from "struct linux_binprm"? You can use the *argv directly with following codes. In the do_execve_common(), insert some codes as following:
argc = count(argv, MAX_ARG_STRINGS);
i = 0;
while (i < argc)
{
const char __user *str;
int len;
ret = -EFAULT;
str = get_user_arg_ptr(argv, i);
if (IS_ERR(str))
goto out;
len = strnlen_user(str, MAX_ARG_STRLEN);
if (!len)
goto out;
//copy the str to kernel temporary storage
//NOTE: tmp[] is a string array,
// the memory should have been allocated already for strings storage,
// each string is ended with \0
memcpy(tmp[i], str, len)
}
After executing these codes, I think the argv strings will be all saved in tmp[] array.
. While if you want to get the full command line after binary loader executing, I think at this time the argument page has been setup correctly, then you can try following approach to get the full command line:
There is a function proc_pid_cmdline() in ./fs/proc/base.c file, you can re-use most codes in proc_pid_cmdline() function to get the full command line from the argument page.
Kernel: getting command line and pid_parent in do_execve_common?
I think by the time calling do_execve, the pid & real_parent & comm fields in task_struct are already initialized.
So you can use kernel functions: getpid(), getppid() and get_task_comm() to get what you want. I am not sure these functions are there in your Linux Kernel version. If not, there should be some similar functions.
How to get around the Linux Too Many Arguments limit
edit:
I was finally able to pass <= 256 KB as a single command line argument (see edit (4) in the bottom). However, please read carefully how I did it and decide for yourself if this is a way you want to go. At least you should be able to understand why you are 'stuck' otherwise from what I found out.
With the coupling of ARG_MAX
to ulim -s
/ 4 came the introduction of MAX_ARG_STRLEN
as max. length of an argument:
/*
* linux/fs/exec.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
...
#ifdef CONFIG_MMU
/*
* The nascent bprm->mm is not visible until exec_mmap() but it can
* use a lot of memory, account these pages in current->mm temporary
* for oom_badness()->get_mm_rss(). Once exec succeeds or fails, we
* change the counter back via acct_arg_size(0).
*/
...
static bool valid_arg_len(struct linux_binprm *bprm, long len)
{
return len <= MAX_ARG_STRLEN;
}
...
#else
...
static bool valid_arg_len(struct linux_binprm *bprm, long len)
{
return len <= bprm->p;
}
#endif /* CONFIG_MMU */
...
static int copy_strings(int argc, struct user_arg_ptr argv,
struct linux_binprm *bprm)
{
...
str = get_user_arg_ptr(argv, argc);
...
len = strnlen_user(str, MAX_ARG_STRLEN);
if (!len)
goto out;
ret = -E2BIG;
if (!valid_arg_len(bprm, len))
goto out;
...
}
...
MAX_ARG_STRLEN
is defined as 32 times the page size in linux/include/uapi/linux/binfmts.h
:
...
/*
* These are the maximum length and maximum number of strings passed to the
* execve() system call. MAX_ARG_STRLEN is essentially random but serves to
* prevent the kernel from being unduly impacted by misaddressed pointers.
* MAX_ARG_STRINGS is chosen to fit in a signed 32-bit integer.
*/
#define MAX_ARG_STRLEN (PAGE_SIZE * 32)
#define MAX_ARG_STRINGS 0x7FFFFFFF
...
The default page size is 4 KB so you cannot pass arguments longer than 128 KB.
I can't try it now but maybe switching to huge page mode (page size 4 MB) if possible on your system solves this problem.
For more detailed information and references see this answer to a similar question on Unix & Linux SE.
edits:
(1)
According to this answer one can change the page size of x86_64
Linux to 1 MB by enabling CONFIG_TRANSPARENT_HUGEPAGE
and setting CONFIG_TRANSPARENT_HUGEPAGE_MADVISE
to n
in the kernel config.
(2)
After recompiling my kernel with the above configuration changes getconf PAGESIZE
still returns 4096.
According to this answer CONFIG_HUGETLB_PAGE
is also needed which I could pull in via CONFIG_HUGETLBFS
. I am recompiling now and will test again.
(3)
I recompiled my kernel with CONFIG_HUGETLBFS
enabled and now /proc/meminfo
contains the corresponding HugePages_*
entries mentioned in the corresponding section of the kernel documentation.
However, the page size according to getconf PAGESIZE
is still unchanged. So while I should be able now to request huge pages via mmap
calls, the kernel's default page size determining MAX_ARG_STRLEN
is still fixed at 4 KB.
(4)
I modified linux/include/uapi/linux/binfmts.h
to #define MAX_ARG_STRLEN (PAGE_SIZE * 64)
, recompiled my kernel and now your code produces:
...
117037
123196
123196
129680
129680
136505
143689
151251
159211
...
227982
227982
239981
239981
252611
252611
265906
./testCL: line 11: ./foo: Argument list too long
279901
./testCL: line 11: ./foo: Argument list too long
294632
./testCL: line 11: ./foo: Argument list too long
So now the limit moved from 128 KB to 256 KB as expected.
I don't know about potential side effects though.
As far as I can tell, my system seems to run just fine.
Related Topics
Rpm Spec to Require Specific Rhel Release
Floating Point Exception (Core Dumped) While Doing Division in Assembly
Why Do My Keystrokes Turn into Crazy Characters After I Dump a Bunch of Binary Data into My Terminal
Linux Read Whitespaces and Special Characters
How to Find/Cut for Only The Filename from an Output of Ls -Lrt in Perl
How to Detect Out-Of-Memory Segfaults
Why Is This Int $0X10 Bios Int Not Working on Linux
Succinct Way to Print All Lines Up Until The Last Line That Matches a Given Pattern
Headless Protractor Tests Don't Plug on Xvfb
Linking with 32Bit Libraries Under Linux 64Bit
Printing Floating Point Numbers in Assembler
Rmpi: Cannot Use Mpi_Comm_Spawn API
Error While Building Pjsip in Linux
Grep in File and Replace String
Passing a Command with Arguments as a String to Docker Run
Yocto for Nvidia Jetson Fails Because of Gcc 7 - Cannot Compute Suffix of Object Files