Line 1: |
Line 1: |
| Due to restrictions imposed by several kernel APIs CRIU uses, the tools can only work with run with root privileges. The plan is to provide [[user-mode]], but it will have restrictions. | | Due to restrictions imposed by several kernel APIs CRIU uses, the tools can only work with run with root privileges. The plan is to provide [[user-mode]], but it will have restrictions. |
| | | |
− | In the latter case, the following security restrictions would apply:
| + | == Service mode == |
− | <pre>
| + | |
− | Legend:
| + | If CRIU is run as [[CLI/cmd/service|service]] from root, make sure the connection socket is restricted to unauthorized access. The service doesn't make any additional checks about the RPC caller, it just goes and performs the requested action. |
− | cr_* -- ids of the calling user;
| |
− | others -- ids of process that we're trying to dump/restore;
| |
− | </pre>
| |
− | * criu will refuse to '''dump/restore''' process if [se]?uid is not equal to cr_uid
| |
− | * criu will refuse to '''dump/restore''' process if [se]?gid is not equal to cr_gid or cr_groups do not contain it
| |
− | * criu will refuse to '''restore''' process if cr_groups don't contain groups
| |
− | * criu will refuse to '''dump/restore''' any bits set in any capability set
| |
| | | |
| == See also == | | == See also == |
Line 16: |
Line 9: |
| CRIU has security issues when working with [[Userns|user namespaces]] and [[selinux]] | | CRIU has security issues when working with [[Userns|user namespaces]] and [[selinux]] |
| | | |
− | == Code example ==
| |
− | Here is a simplified version of code from security.c.
| |
− |
| |
− | <source lang="c" style="font-size: 120%;">
| |
− | bool check_uids()
| |
− | {
| |
− | if (cr_uid == 0)
| |
− | return true;
| |
− |
| |
− | if (cr_uid == ruid && cr_uid == suid && cr_uid == eid)
| |
− | return true;
| |
− |
| |
− | return false;
| |
− | }
| |
− |
| |
− | bool check_gids()
| |
− | {
| |
− | if (cr_gid == 0)
| |
− | return true;
| |
− |
| |
− | if ((contains(cr_groups, rgid) || cr_gid == rgid) &&
| |
− | (contains(cr_groups, egid) || cr_gid == egid) &&
| |
− | (contains(cr_groups, sgid) || cr_gid == sgid))
| |
− | return true;
| |
− |
| |
− | return false;
| |
− | }
| |
− |
| |
− | /*
| |
− | * There is no need to check groups on dump, because if uids and gids match
| |
− | * then groups will match too. Btw, getting groups on dump is problematic.
| |
− | * We can't parse proc, as it contains only first 32 groups. And we can't use
| |
− | * getgrouplist, as it reads /etc/group which depends on the namespace.
| |
− | *
| |
− | * On restore we're getting groups from imgs and can check if user didn't add
| |
− | * wrong groups by modifying images.
| |
− | */
| |
− | bool check_groups()
| |
− | {
| |
− | if (cr_gid == 0)
| |
− | return true;
| |
− |
| |
− | for (i = 0; i < ngroups; ++i) {
| |
− | if (!contains(cr_groups, groups[i]))
| |
− | return false;
| |
− | }
| |
− |
| |
− | return true;
| |
− | }
| |
− |
| |
− | bool check_caps()
| |
− | {
| |
− | /*
| |
− | * Impose the most strict requirements for now.
| |
− | * "Real" root user can use any caps, other users may
| |
− | * use none. Later we will implement more sophisticated
| |
− | * security model.
| |
− | */
| |
− |
| |
− | if (cr_uid == 0 && cr_gid == 0)
| |
− | return true;
| |
− |
| |
− | for (i = 0; i < CR_CAP_SIZE; i++) {
| |
− | if (inh[i] != 0 || eff[i] != 0 || prm[i] != 0)
| |
− | return false;
| |
− | }
| |
− |
| |
− | return true;
| |
− | }
| |
− |
| |
− | bool may_dump()
| |
− | {
| |
− | return check_uids() &&
| |
− | check_gids() &&
| |
− | check_caps();
| |
− | }
| |
− |
| |
− | bool may_restore()
| |
− | {
| |
− | return check_uids() &&
| |
− | check_gids() &&
| |
− | check_groups() &&
| |
− | check_caps();
| |
− | }
| |
− | </source>
| |
| | | |
| [[Category: API]] | | [[Category: API]] |