Permission denied with the httpServer example

Hello,
I had succefully installed the httpServer sample, but now I have a problem…
I tested the Run shell command page and I did a /legato/systems/current/bin/app status and it was a success. But now what I’m interested for is the cm command or even a custom command. But I tried a lot of things and I’m unable to launch them… Everytime I have permission denied.

From my invetisgations I found that the binaries cm was in fact a symlink directed to a read-only directory. But when I look the permissions of the file and the symlink I normally have the permissions to execute it.

I hope you can help me, it’s very frustrating…

Reunan

Hi, Reunan,

What you’re seeing are the limits placed on your app by the sandbox that it is running in.

To use the cm tool, you would have to bind that executable and the libraries it needs into your sandbox using the “requires: { file: { … } }” directives in your Component.cdef or .adef file, then you need to grant permission to your app to access the modem services APIs that you want to use from the cm tool by binding its client-side interfaces using a “bindings:” section in your .adef or your .sdef file.

We should soon (in time for the upcoming 16.10 release) have a tool for interactively discovering files your app is trying to access and binding them into your app’s sandbox. In the meantime, you can strace your process (using ‘strace -f -p ’) to watch for open() calls that fail to detect what you need that is missing from your sandbox).

To discover what bindings are missing, use the ‘sdir list’ tool and look in the WAITING CLIENTS list when your program hangs because it is trying to connect an interface that is not bound to anything.

I hope this helps.

For more info on using sandboxes: http://legato.io/legato-docs/latest/howToSecuritySandboxUse.html

Of course, you can also run your web server unsandboxed, but I would strongly recommend against deploying anything on the public Internet like that (or even on a private network for any significant length of time). You don’t want your device becoming part of a bot net or something. Also, beware that any permissions you grant to your web server app can potentially be exploited by an attacker. So, be careful. The shell program page in the demo is really just a toy feature for exploring sandbox limits. It should really be disabled for any production web server.

Cheers,

–Jen

Hello Jen,

First, hanks for your response, it does help me to have a better understanding of how sandboxes work.
Unfortunately, I was unable to run the cm command in the shell page.
There is my adef files:

 sandboxed: true
 start: auto
 processes:
 {
    envVars:
    {
        HOME="/"
    }

    run:
    {
        (lighttpd -m /modlibs/ -D -f /cfg/lighttpd.conf )
    }
    maxCoreDumpFileBytes: 512K maxFileBytes: 512K
}
version: 1.0.0
maxFileSystemBytes: 512K
bundles:
{
    file:
    {
        [x] binaries/lighttpd /usr/local/bin/
    }
    dir:
    {
        binaries/lib /modlibs
        pages /pages
        cfg /cfg
    }
}
requires:
{
    dir: { /proc /    // needed by `app` script, and for listing running processes
        /bin /
        /sbin /
        /usr/lib /usr/
        /usr/bin /usr/
        /usr/include /usr/
        /legato/systems/current/bin /legato/systems/current/
        /legato/systems/current/lib /legato/systems/current/
        /legato/systems/current/apps /legato/systems/current/
    }

    device:
    {
        [rw] /dev/null /dev/null
        [r] /dev/urandom /dev/urandom
        [r] /dev/random /dev/random
    }

    configTree:
    {
        [r] system
    }
    
    file:
    {
        /lib/libutil.so.1 /lib/libutil.so.1
        /etc/nsswitch.conf /etc/nsswitch.conf
        /lib/libnss_compat.so.2 /lib/libnss_compat.so.2
        /lib/libnsl.so.1 /lib/libnsl.so.1
        /lib/libproc-3.2.8.so /lib/libproc-3.2.8.so
        /etc/passwd /etc/passwd    // needed by python to lookup user
        /lib/libcrypto.so.1.0.0 /lib/libcrypto.so.1.0.0
        /legato/systems/current/version /legato/systems/current/version
        /legato/systems/current/status /legato/systems/current/status
        /legato/systems/current/apps/MuxTools/read-only/bin/mux /usr/bin/mux
        /legato/systems/current/apps/MuxTools/read-only/lib/libComponent_mux.so /usr/lib/libComponent_mux.so
        /legato/systems/current/apps/tools/read-only/bin/cm /usr/bin/cm
        /legato/systems/current/apps/tools/read-only/lib/libComponent_cm.so /usr/lib/libComponent_cm.so
    }
}
bindings:
{
        *.le_cfg -> <root>.le_cfg
        *.le_update -> <root>.le_update
        *.le_tool -> <root>.le_tools
        *.le_appInfo -> <root>.le_appInfo
        *.muxCtrlService -> <root>.muxCtrlService
        *.le_gnss -> <root>.le_gnss
        *.le_adc -> <root>.le_adc
        *.mux -> <root>.mux
        *.cm -> <root>.cm
}

As you can see I added the files using the requires: { file: { ... } } directives, and then I added the needed APIs in the binding section. With this configuration it doesn’t work either. (I had almost the same before). Maybe I’m missing something…

There is where the permission denied is fired in the strace -f -p output:

[pid  3108] uname({sys="Linux", node="swi-mdm9x15", ...}) = 0
[pid  3108] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f3e000
[pid  3108] access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
[pid  3108] open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/tls/v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/tls/v7l/neon/vfp", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/tls/v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/tls/v7l/neon", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/tls/v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/tls/v7l/vfp", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/tls/v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/tls/v7l", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/tls/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/tls/neon/vfp", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/tls/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/tls/neon", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/tls/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/tls/vfp", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/tls", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/v7l/neon/vfp", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/v7l/neon", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/v7l/vfp", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/v7l", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/neon/vfp", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/neon", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/lib/vfp", 0xbed6f290) = -1 ENOENT (No such file or directory)
[pid  3108] open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
[pid  3108] read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\10{\231A4\0\0\0"..., 512) = 512
[pid  3108] fstat64(3, {st_mode=S_IFREG|0755, st_size=1226668, ...}) = 0
[pid  3108] mmap2(0x41980000, 1259976, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x41980000
[pid  3108] mprotect(0x41aa6000, 32768, PROT_NONE) = 0
[pid  3108] mmap2(0x41aae000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x126000) = 0x41aae000
[pid  3108] mmap2(0x41ab2000, 6600, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x41ab2000
[pid  3108] close(3)                    = 0
[pid  3108] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f3d000
[pid  3108] set_tls(0xb6f3d4c0, 0xb6f3dba8, 0x41978050, 0xb6f3d4c0, 0x41978050) = 0
[pid  3108] mprotect(0x41aae000, 8192, PROT_READ) = 0
[pid  3108] mprotect(0x41977000, 4096, PROT_READ) = 0
[pid  3108] getuid32()                  = 1016
[pid  3108] stat64("/etc/busybox.conf", 0xbed6f8d8) = -1 ENOENT (No such file or directory)
[pid  3108] getgid32()                  = 1016
[pid  3108] setgid32(1016)              = 0
[pid  3108] setuid32(1016)              = 0
[pid  3108] brk(0)                      = 0xa7000
[pid  3108] brk(0xc8000)                = 0xc8000
[pid  3108] getpid()                    = 3108
[pid  3108] rt_sigaction(SIGCHLD, {SIG_DFL, [CHLD], SA_RESTART|0x4000000}, {SIG_DFL, [], 0}, 8) = 0
[pid  3108] rt_sigaction(SIGHUP, {SIG_DFL, [HUP], SA_RESTART|0x4000000}, {SIG_DFL, [], 0}, 8) = 0
[pid  3108] getppid()                   = 3096
[pid  3108] getcwd("/pages", 4096)      = 7
[pid  3108] rt_sigaction(SIGINT, NULL, {SIG_DFL, [], 0}, 8) = 0
[pid  3108] rt_sigaction(SIGINT, {0x32fc4, ~[RTMIN RT_1], 0x4000000 /* SA_??? */}, NULL, 8) = 0
[pid  3108] rt_sigaction(SIGQUIT, NULL, {SIG_DFL, [], 0}, 8) = 0
[pid  3108] rt_sigaction(SIGQUIT, {SIG_IGN, ~[RTMIN RT_1], 0x4000000 /* SA_??? */}, NULL, 8) = 0
[pid  3108] rt_sigaction(SIGTERM, NULL, {SIG_DFL, [], 0}, 8) = 0
[pid  3108] rt_sigaction(SIGTERM, {SIG_DFL, ~[RTMIN RT_1], 0x4000000 /* SA_??? */}, NULL, 8) = 0
[pid  3108] fcntl64(2, F_DUPFD, 10)     = 10
[pid  3108] dup2(1, 2)                  = 2
[pid  3108] stat64("/sbin/cm", 0xbed6f4c8) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/usr/sbin/cm", 0xbed6f4c8) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/bin/cm", 0xbed6f4c8) = -1 ENOENT (No such file or directory)
[pid  3108] stat64("/usr/bin/cm", 0xbed6f4c8) = -1 EACCES (Permission denied)
[pid  3108] write(2, "sh: ", 4)         = 4
[pid  3108] write(2, "cm: Permission denied", 21) = 21
[pid  3108] write(2, "\n", 1)           = 1
[pid  3108] dup2(10, 2)                 = 2
[pid  3108] close(10)                   = 0
[pid  3108] exit_group(127)             = ?
[pid  3108] +++ exited with 127 +++
[pid  3096] <... read resumed> "sh: ", 4096) = 4
[pid  3096] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=3108, si_status=127, si_utime=0, si_stime=2} ---

Then when I did a sdir list there was not WAINTING CLIENTS…

Did I miss something ?

Cheers,
Reunan

I think I’m getting closer !

I reinstalled legato, I donwloaded the latest httpServer sample and I changed some little things in it :

sandboxed: true

bundles:
{
    file:
    {
        [x] binaries/lighttpd /usr/local/bin/

    }

    dir:
    {
        binaries/lib /modlibs
        pages /pages
        cfg /cfg
    }
}

requires:
{
    file:
    {
        /lib/libutil.so.1 /lib/libutil.so.1
        /etc/nsswitch.conf /etc/nsswitch.conf
        /lib/libnss_compat.so.2 /lib/libnss_compat.so.2
        /lib/libnsl.so.1 /lib/libnsl.so.1
        /lib/libproc-3.2.8.so /lib/libproc-3.2.8.so
        /etc/passwd /etc/passwd    // needed by python to lookup user
        /lib/libcrypto.so.1.0.0 /lib/libcrypto.so.1.0.0
        /legato/systems/current/version /legato/systems/current/version
        /legato/systems/current/status /legato/systems/current/status
        /legato/systems/current/apps/tools/read-only/lib/libComponent_cm.so /legato/systems/current/lib/
    }

    dir:
    {
        /proc /    // needed by `app` script, and for listing running processes
        /bin /
        /sbin /
        /usr/lib /usr/
        /usr/bin /usr/
        /usr/include /usr/
        /legato/systems/current/bin /legato/systems/current/
        /legato/systems/current/lib /legato/systems/current/
        /legato/systems/current/apps /legato/systems/current/
    }

    device:
    {
        [rw] /dev/null /dev/null
        [r] /dev/urandom /dev/urandom
        [r] /dev/random /dev/random
    }

    configTree:
    {
        [r] system
    }
}

bindings:
{
	//*.cm.cm.le_cfg -> <root>.le_cfg
 
    *.le_update -> <root>.le_update
    *.le_appInfo -> <root>.le_appInfo
    *.le_adc -> <root>.le_adc
    *.cm -> <root>.cm
    *.le_cfg -> <root>.le_cfg
   
}
start: auto
processes:
{
    envVars:
    {
        HOME="/"
    }

    run:
    {
        (lighttpd -m /modlibs/ -D -f /cfg/lighttpd.conf )
    }
}

Now I have something in the outpu of the sdir list command:

    WAITING CLIENTS

        [pid  1731] httpServer.cm.cm.le_cfg UNBOUND  (protocol ID = '8a26e6c5c2c76df02e412df515bd9f71')
        [pid  2169] httpServer.cm.cm.le_cfg UNBOUND  (protocol ID = '8a26e6c5c2c76df02e412df515bd9f71')
        [pid  2527] httpServer.cm.cm.le_cfg UNBOUND  (protocol ID = '8a26e6c5c2c76df02e412df515bd9f71')

Now I tried to do add this binding to my .adef file (*.cm.cm.le_cfg -> <root>.le_cfg) but I have this error:
Unexpected character '.' Expected '->' httpServer.adef /httpServer line 63 C/C++ Problem

According to the file adefParser.cpp located in /legato-16.07.0/framework/tools/mkTools/parser the accepted binding formats are those:

  In a .adef, the binding must be one of the following forms:
    External bindings:
      "*.clientInterface -> app.exportedInterface"
      "clientExe.clientComponent.clientInterface -> app.exportedInterface"
      "*.clientInterface -> <user>.exportedInterface"
      "clientExe.clientComponent.clientInterface -> <user>.exportedInterface"
    Internal bindings:
      "clientExe.clientComponent.clientInterface -> serverExe.serverComponent.serverInterface"

I’m a little bit confused…
EDIT:
I “successfully” (in fact I don’t know) do the bindings in the .sdef file, (I don’t have any parse error) :

bindings:
{
    httpServer.*.le_cfg -> <root>.le_cfg
    <root>.le_fwupdate -> fwupdateService.le_fwupdate
}

But now I don’t have waiting clients when I do sdir list, and I have again a permission denied…

I hope you can help me I really struggle with the sandboxes :sweat_smile:
cheers,
Reunan

have you solved your problem?

I have the same issue of trying to execute cm liked command but no luck.

I’ve try to run the app unsandboxed, but the green board event don’t let me install the app.