• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mozilla / mozregression / 11075188294

27 Sep 2024 05:37PM UTC coverage: 89.401%. First build
11075188294

Pull #1724

github

web-flow
Merge 806b99e79 into 1b62e6d7a
Pull Request #1724: Bug 1899515 - Inform users of maybe missing AppArmor rules

12 of 46 new or added lines in 3 files covered. (26.09%)

2539 of 2840 relevant lines covered (89.4%)

13.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.19
/mozregression/linux_utils.py
1
"""
2
Various linux-specific tools
3
"""
4

5
import os
14✔
6
import sys
14✔
7

8

9
def check_unprivileged_userns(logger):
14✔
10
    """
11
    Some distribution started to block unprivileged user namespaces via
12
    AppArmor.  This might result in crashes on older builds, and in degraded
13
    sandbox behavior.  It is fixed with an AppArmor profile that allows the
14
    syscall to proceed, but this is path dependant on the binary we download
15
    and needs to be installed at a system level, so we can only advise people
16
    of the situation.
17

18
    The following sys entry should be enough to verify whether it is blocked or
19
    not, but the Ubuntu security team recommend cross-checking with actual
20
    syscall.  This code is a simplification of how Firerox does it, cf
21
    https://searchfox.org/mozilla-central/rev/23efe2c8c5b3a3182d449211ff9036fb34fe0219/security/sandbox/linux/SandboxInfo.cpp#114-175
22
    and has been the most reliable way so far (shell with unshare would not
23
    reproduce EPERM like we want).
24

25
    Return False if there is no problem or True if the user needs to fix their
26
    setup.
27
    """
28

29
    apparmor_file = "/proc/sys/kernel/apparmor_restrict_unprivileged_userns"
14✔
30
    if not os.path.isfile(apparmor_file):
14✔
NEW
31
        return False
5✔
32

33
    with open(apparmor_file, "r") as f:
9✔
34
        if f.read().strip() != "1":
9✔
35
            return False
5✔
36

NEW
37
    import ctypes
4✔
NEW
38
    import errno
4✔
NEW
39
    import platform
4✔
NEW
40
    import signal
4✔
41

42
    # Values are from
43
    # https://github.com/hrw/syscalls-table/tree/163e238e4d7761fcf6ac500aad92d53ac88d663a/system_calls/tables
44
    # imported from linux kernel headers
NEW
45
    SYS_clone = {
4✔
46
        "i386": 120,
47
        "x32": 1073741880,
48
        "x86_64": 56,
49
        "arm": 120,
50
        "armv7l": 120,
51
        "arm64": 220,
52
        "aarch64": 220,
53
        "aarch64_be": 220,
54
        "armv8b": 220,
55
        "armv8l": 220,
56
    }.get(platform.machine())
NEW
57
    if not SYS_clone:
4✔
NEW
58
        logger.warning(
×
59
            "Unprivileged user namespaces might be disabled, but unsupported platform? {}".format(
60
                platform.machine()
61
            )
62
        )
NEW
63
        return False
×
64

NEW
65
    libc = ctypes.CDLL(None, use_errno=True)
4✔
66

NEW
67
    logger.warning(
4✔
68
        "Unprivileged user namespaces might be disabled. Checking clone() + unshare() syscalls ..."
69
    )
70

NEW
71
    try:
4✔
72
        # Introduced in 3.12 which is the version of Ubuntu 24.04
NEW
73
        clone_newuser = os.CLONE_NEWUSER
4✔
NEW
74
        clone_newpid = os.CLONE_NEWPID
1✔
NEW
75
    except AttributeError:
3✔
76
        # From
77
        # https://github.com/torvalds/linux/blob/5bbd9b249880dba032bffa002dd9cd12cd5af09c/include/uapi/linux/sched.h#L31-L32
78
        # Last change 12 years ago, so it should be a stable fallback
NEW
79
        clone_newuser = 0x10000000
3✔
NEW
80
        clone_newpid = 0x20000000
3✔
81

NEW
82
    pid = libc.syscall(SYS_clone, signal.SIGCHLD.value | clone_newuser, None, None, None, None)
4✔
83

NEW
84
    if pid == 0:
4✔
85
        # Child side ...
NEW
86
        rv = libc.unshare(clone_newpid)
×
NEW
87
        _errno = ctypes.get_errno()
×
NEW
88
        if rv < 0:
×
NEW
89
            sys.exit(_errno)
×
NEW
90
        sys.exit(0)
×
91
    else:
NEW
92
        (pid, statuscode) = os.waitpid(pid, 0)
4✔
NEW
93
        exitcode = os.waitstatus_to_exitcode(statuscode)
4✔
94

NEW
95
        if exitcode == 0:
4✔
NEW
96
            return False
×
97

NEW
98
        if exitcode == errno.EPERM:
4✔
NEW
99
            logger.warning(
4✔
100
                "Unprivileged user namespaces is disabled. This is likely because AppArmor policy "
101
                "change. Please refer to {} to learn how to setup AppArmor so that mozregression "
102
                "works correctly. Missing AppArmor profile can lead to crashes or to incorrectly "
103
                "sandboxed processes.".format(
104
                    "https://mozilla.github.io/mozregression/documentation/usage.html#unprivileged-user-namespaces"  # noqa: E501
105
                )
106
            )
NEW
107
            logger.warning(
4✔
108
                "If you already applied the suggested fix, then this warning can be ignored. "
109
                "It can also be silenced by the --dont-check-userns flag."
110
                "Another side effect is that browser's tab may crash because "
111
                "they incorrectly test for the feature. If your regression "
112
                "window covers that, you may want to set MOZ_ASSUME_USER_NS=0 "
113
                "environmnent variable before launching mozregression."
114
            )
NEW
115
            return True
4✔
116

NEW
117
        logger.warning(
×
118
            "Unexpected exit code {} while performing user namespace "
119
            "checks. You might want to file a bug.".format(exitcode)
120
        )
121

NEW
122
    return False
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc