Bug 1293934 - seccomp: SECCOMP_RET_ERRNO returns max 12bit errno, instead of documented 16bit
seccomp: SECCOMP_RET_ERRNO returns max 12bit errno, instead of documented 16bit
Status: CLOSED NOTABUG
Product: Fedora
Classification: Fedora
Component: kernel (Show other bugs)
23
All Linux
medium Severity medium
: ---
: ---
Assigned To: Kernel Maintainer List
Fedora Extras Quality Assurance
:
Depends On:
Blocks: 1281852
  Show dependency treegraph
 
Reported: 2015-12-23 10:15 EST by Miroslav Vadkerti
Modified: 2016-07-12 05:44 EDT (History)
9 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2016-07-12 05:44:15 EDT
Type: Bug
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
reproducer.c (695 bytes, text/plain)
2015-12-23 10:15 EST, Miroslav Vadkerti
no flags Details

  None (edit)
Description Miroslav Vadkerti 2015-12-23 10:15:45 EST
Created attachment 1108977 [details]
reproducer.c

Description of problem:
seccomp seems to be returning 12bit errno max instead of expected 16bit if SECCOMP_RET_ERRNO used.

This minimal reproducer is enough to reprodude the issue. I am attaching it also

---- reproducer start ----
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <seccomp.h>
#include <unistd.h>

#define TESTING_SCERRNO 0x1234 /* 4660 */

int main(int argc, char **argv)
{   
    scmp_filter_ctx ctx = NULL;
    int ret;
    
    ctx = seccomp_init(SCMP_ACT_ALLOW);
    if (ctx == NULL)
        exit(1);
    
    if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(TESTING_SCERRNO), SCMP_SYS(dup2), 1,
                         SCMP_CMP(0, SCMP_CMP_EQ, 0)) < 0)
                exit(1);
    
    if (seccomp_load(ctx) < 0)
        exit(1);
    
    seccomp_release(ctx);

    ret = dup2(0, 42);
    
    printf("%d %d %hd\n", ret, errno, TESTING_SCERRNO);

    return 0;
}
---- reproducer start ----

To compile and run use:
# gcc -lseccomp -o reproducer reproducer.c 
# ./reproducer

According to docs:
SECCOMP_RET_ERRNO:
	Results in the lower 16-bits of the return value being passed
	to userland as the errno without executing the system call.

It should return according to the documentation [1]:
-1 4660 4660

Instead on Fedora returns (it seems to return only 12bit integer max):
-1 4095 4660

Version-Release number of selected component (if applicable):
kernel-4.2.8-300.fc23.x86_64
kernel-4.4.0-0.rc6.git0.1.fc24.x86_64

How reproducible:
100%

Steps to Reproduce:
1. Compile attached reproducer as written in description

Actual results:
-1 4095 4660

Expected results:
-1 4660 4660

[1] https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt
Comment 4 Paul Moore 2016-01-06 18:40:49 EST
For reference, the kernel sets the maximum errno value (MAX_ERRNO) to 4095, see include/linux/err.h.

Up until Linux 4.0 there was a bug where seccomp would allow setting a errno value beyond MAX_ERRNO.  It was fixed with the following patch:

  commit 580c57f1076872ebc2427f898b927944ce170f2d
  Author: Kees Cook <keescook@chromium.org>
  Date:   Tue Feb 17 13:48:00 2015 -0800

    seccomp: cap SECCOMP_RET_ERRNO data to MAX_ERRNO
    
    The value resulting from the SECCOMP_RET_DATA mask could exceed MAX_ERRNO
    when setting errno during a SECCOMP_RET_ERRNO filter action.  This makes
    sure we have a reliable value being set, so that an invalid errno will not
    be ignored by userspace.
    
    Signed-off-by: Kees Cook <keescook@chromium.org>
    Reported-by: Dmitry V. Levin <ldv@altlinux.org>
    Cc: Andy Lutomirski <luto@amacapital.net>
    Cc: Will Drewry <wad@chromium.org>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

The kernel patch does not appear to be in RHEL7 as I am writing this comment.

The libseccomp library has also added an errno check with the following patch:

  commit 0d287caf43792239b107ee3215b32b8bc901f9c3
  Author: Paul Moore <pmoore@redhat.com>
  Date:   Sat Aug 29 20:05:19 2015 -0400

    api: limit errno values to MAX_ERRNO
    
    It turns out that userspace behaves oddly when given an errno value
    greater than MAX_ERRNO, so much so that the kernel seccomp mechanism
    has started blocking filters with bad errno values.  Let's try to
    catch the problem at rule addition time to make things easier to
    spot and fix.
    
    Signed-off-by: Paul Moore <pmoore@redhat.com>

The libseccomp patch is not present in any released versions of the library but will be included in the next release.
Comment 5 Jiri Jaburek 2016-06-30 12:22:33 EDT
As this seems like a end-user issue and was fixed in our test suite (using errno of <12bits), is there anything to be done on the kernel or libseccomp side? Or can we close this as NOTABUG?
Comment 7 Miroslav Vadkerti 2016-07-12 05:44:15 EDT
I do not think so .. thanks .. CLOSING AS NOTABUG

(In reply to Jiri Jaburek from comment #5)
> As this seems like a end-user issue and was fixed in our test suite (using
> errno of <12bits), is there anything to be done on the kernel or libseccomp
> side? Or can we close this as NOTABUG?

Note You need to log in before you can comment on or make changes to this bug.