Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xargs: exec ... Argument list too long #40

Closed
d4rken opened this issue Aug 10, 2016 · 6 comments
Closed

xargs: exec ... Argument list too long #40

d4rken opened this issue Aug 10, 2016 · 6 comments

Comments

@d4rken
Copy link

d4rken commented Aug 10, 2016

toybox 0.7.1

On some Android devices (N5@6.0) using a chain of find .... | xargs .... stat ...., yields the error Argument list too long.

Some googlfu shows that this is likely related to the argument exceeding the kernels ARG_MAX value.
Androids ARG_MAX according to this 131072.

Manually limiting the xargs argument length using -s bytes fixes this for me.

I've looked at the code for xarg in toybox but could not figure out yet how the max argument length is determined.

Busybox doesn't seem to run into this issue using the same command on the same device. Busybox seems to have some sanity checks, adjusting the argument length if necessary.

Could there be an issue with how toybox's xarg determines the default argument length on Android?

@landley
Copy link
Owner

landley commented Aug 10, 2016

On 08/10/2016 07:44 AM, Matthias Urhahn wrote:

On some Android devices (N5@6.0) using a chain of |find .... | xargs
.... stat ....|, yields the error |Argument list too long|.

Some googlfu shows that this is likely related to the argument exceeding
the kernels ARG_MAX value.
Androids ARG_MAX according to this 131072
https://github.com/android/platform_bionic/blob/master/libc/kernel/uapi/linux/limits.h.

The Linux kernel removed that limit in 2007
(https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=b6a2fea39318
went into the 2.6.22 release).

That said, let's cd to a directory with a lot of files in it:

$ find . | wc
68971 69024 3159459
$ find . | toybox xargs echo
xargs: exec echo: Argument list too long

And I'm seeing a limit here too. Hmmm...

Manually limiting the xargs argument length using |-s bytes| fixes this
for me.

The kernel should not be enforcing this? Maybe something else is? There
isn't an obvious ulimit for this... Ah, in include/uapi/linux/limits.h:

#define ARG_MAX 131072 /* # bytes of args + environ for exec() */

And that's used in fs/exec.c:

/*

  • We've historically supported up to 32 pages (ARG_MAX)

  • of argument strings even with small stacks
    */
    if (size <= ARG_MAX)
    return page;

    /*

  • Limit to 1/4-th the stack size for the argv+env strings.

  • This ensures that:

    • the remaining binfmt code will not run out of stack space,
    • the program will have a reasonable amount of stack left
  • to work from.
    */
    rlim = current->signal->rlim;
    if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) {
    put_page(page);
    return NULL;
    }

Ok, so that's still there as a MINIMUM, and the maximum is 1/4 the
current stack size ulimit. According to ulimit -s that defaults to 8192
kilobytes (at least on xubuntu 14.04), so 1/4 of 8 megs is 2 megs. And...

$ find . | head -n 40000 | wc
40000 40002 1853620
$ find . | head -n 40000 | toybox xargs echo | wc
1 40002 1853620

Yup, the actual default limit is way more than 131072, and that
default is arbitrarily adjustable even for normal users:

$ ulimit -Hs
unlimited
$ ulimit -s 9999999
$ find . | toybox xargs echo | wc
1 69023 3159436

(Huh, what happens if I set the stack size limit to less than 131072
and then try to exec stuff? Not trying it on my work netbook just now,
thanks...)

I've looked at the code for xarg in toybox but could not figure out yet
how the max argument length is determined.

It didn't enforce a default maximum length limit because as far as I
knew the kernel hadn't required one for 9 years. I worked out the math
for enforcing such a limit back when I first did xargs:

http://landley.net/notes-2011.html#17-12-2011

So it's not hard to add a default, but what the default should be isn't
obvious. Back when I noticed the kernel had changed its logic I
checked that I could feed it more than 131072 bytes, and I could, so I
removed the limit. (Not just from xargs, but from find in commit
aa784b0 and possibly elsewhere.)

Busybox doesn't seem to run into this issue using the same command on
the same device. Busybox seems to have some sanity checks
https://git.busybox.net/busybox/tree/findutils/xargs.c#n529, adjusting
the argument length if necessary.

The sanity checks are there (-s is implemented), toybox just doesn't
have a default value if you don't specify one.

Could there be an issue with how toybox's |xarg| determines the default
argument length on Android?

See above.

There's a sysconf(_SC_ARG_MAX), which does appear to be calculating this
properly (at least built against glibc, musl is giving me 131072 and I
still haven't got a host bionic toolchain because building bionic
outside of AOSP was nontrivial when I looked at it).

Oh well, use the sysconf and then file a bug against musl. (Elliott will
probably notice this, and if not he'll notice the commit.)

Thanks for the heads up,

Rob

@d4rken
Copy link
Author

d4rken commented Aug 11, 2016

Thanks for the details, very intresting.

Oh well, use the sysconf and then file a bug against musl.

I'm not sure I understood this. Should I file this somewhere else?

(Elliott will probably notice this, and if not he'll notice the commit.)

What commit?

@landley
Copy link
Owner

landley commented Aug 11, 2016

On 08/11/2016 12:25 AM, Matthias Urhahn wrote:

Thanks for the details, very intresting.

Oh well, use the sysconf and then file a bug against musl.

I'm not sure I understood this. Should I file this somewhere else?

No, I meant that's how I should fix it in toybox.

(Elliott will probably notice this, and if not he'll notice the
commit.)

What commit?

One I haven't made yet, fixing this. (Busy day, sorry.)

Rob

@enh
Copy link
Contributor

enh commented Sep 20, 2017

thread restarted with patch for xargs (but not find): http://lists.landley.net/pipermail/toybox-landley.net/2017-September/009167.html

@enh-google
Copy link
Collaborator

i think this can be closed now... as of the end of 2019 this is working for bionic, glibc, and macOS.

@landley
Copy link
Owner

landley commented Dec 23, 2019

The magic -4096 is still a little creepy, but yes it seems to be working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants