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

Add rudimental syscall capget/capset #809

Merged
merged 1 commit into from
Jun 4, 2024

Conversation

StanPlatinum
Copy link
Contributor

@StanPlatinum StanPlatinum commented May 6, 2024

Add the capget/capset syscalls & Linux capability support (for prctl later).

Also, a test application has been added to regression/apps/capability.

@StanPlatinum StanPlatinum mentioned this pull request May 6, 2024
@StanPlatinum StanPlatinum changed the title Add syscall capget Add syscall capget/capset May 7, 2024
@StanPlatinum StanPlatinum force-pushed the dev-cap branch 5 times, most recently from 8935b12 to 06f0675 Compare May 15, 2024 08:11
Copy link
Contributor

@tatetian tatetian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for submitting the implementation of Linux capabilities.

My biggest concern is that the implementation proposed by this PR appears to be too rudimental. I call it "rudimental" because it lacks of the essence of the Linux capabilities mechanism. Adding the two system calls is only a good first step, but not enough. The essence of the Linux capabilities, in my opinion, is enforcing its security invariants. They should have been have been done by this PR.

To describe the invariants, I follow the notations adopted by the man page.

  • P(effective), P(permitted), and P(inheritable) denote the effective, permitted, and inheritable capability sets of a process, respectively.
  • P'(effective), P'(permitted), and P'(inheritable) denote the effective, permitted, and inheritable capability sets of a forked or exec'ed process, respectively.
  • F(effective), F(permitted), and F(inheritable) denote the effective, permitted, and inheritable capability sets of a file exec'ed by a process, respectively.

The essence of the Linux capabilities system include but is not limited to the following security invariants categorized by their usage. None of these invariants are enforced by this PR.

When determining whether a privilege operation is allowed or not

  • Invariant. A thread is only allowed to perform privileged operations granted by the capabilities within its P(effective) set.

This invariant must be enforced by changing the specific subsystems or modules that actually conduct the privilege operations. This is too much work and thus can be left out of this PR.

Note that Linux capabilities are per-thread, not per-process. This is a point that is NOT implemented faithfully by this PR.

When passing on capabilities from a parent process to a child on fork or clone

  • Invariant: P'(effective) = P(effective)
  • Invariant: P'(permitted) = P(permitted)
  • Invariant: P'(inheritable) = P(inheritable)

These invariants are trivial. They basically say that capabilities are passed intact to a child.

When adding or dropping the capabilities of a process/thread

The capset system call can be used to adjust the capability sets of a process/thread. The fundamental rule is that the permitted capability set is the superset of all current and future capability sets (until the thread execes a file).

  • Invariant: P(effective) <= P(permitted)
  • Invariant: P(inheritable) <= P(permitted)
  • Invariant: P'(permitted) <= P(permitted)

Here, P'(permitted) means the new value of the permitted capability set.

When execing a file

  • Invariant: P'(permitted) = (P(inheritable) & F(inheritable)) | (F(permitted) & cap_bset)
  • Invariant: P'(effective) = F(effective) ? P'(permitted) : 0
  • Invariant: P'(inheritable) = P(inheritable)

cap_bset denotes the process bounding capability set.

More

There are more invariants to enforce. I only summarize some of them as I read through Chapter 39 Capabilities, The Linux Programming Interface. I expect you to dive into the spec more deeply than I do to come up with a faithful and correct implementation.

kernel/aster-nix/src/process/credentials/static_cap.rs Outdated Show resolved Hide resolved
kernel/aster-nix/src/process/credentials/static_cap.rs Outdated Show resolved Hide resolved
kernel/aster-nix/src/syscall/capset.rs Outdated Show resolved Hide resolved
kernel/aster-nix/src/syscall/capset.rs Outdated Show resolved Hide resolved
kernel/aster-nix/src/syscall/capset.rs Outdated Show resolved Hide resolved
regression/apps/capability/check_cap.c Outdated Show resolved Hide resolved
@StanPlatinum
Copy link
Contributor Author

Thank you for submitting the implementation of Linux capabilities.

My biggest concern is that the implementation proposed by this PR appears to be too rudimental. I call it "rudimental" because it lacks of the essence of the Linux capabilities mechanism. Adding the two system calls is only a good first step, but not enough. The essence of the Linux capabilities, in my opinion, is enforcing its security invariants. They should have been have been done by this PR.

To describe the invariants, I follow the notations adopted by the man page.

  • P(effective), P(permitted), and P(inheritable) denote the effective, permitted, and inheritable capability sets of a process, respectively.
  • P'(effective), P'(permitted), and P'(inheritable) denote the effective, permitted, and inheritable capability sets of a forked or exec'ed process, respectively.
  • F(effective), F(permitted), and F(inheritable) denote the effective, permitted, and inheritable capability sets of a file exec'ed by a process, respectively.

The essence of the Linux capabilities system include but is not limited to the following security invariants categorized by their usage. None of these invariants are enforced by this PR.

When determining whether a privilege operation is allowed or not

  • Invariant. A thread is only allowed to perform privileged operations granted by the capabilities within its P(effective) set.

This invariant must be enforced by changing the specific subsystems or modules that actually conduct the privilege operations. This is too much work and thus can be left out of this PR.

Note that Linux capabilities are per-thread, not per-process. This is a point that is NOT implemented faithfully by this PR.

When passing on capabilities from a parent process to a child on fork or clone

  • Invariant: P'(effective) = P(effective)
  • Invariant: P'(permitted) = P(permitted)
  • Invariant: P'(inheritable) = P(inheritable)

These invariants are trivial. They basically say that capabilities are passed intact to a child.

When adding or dropping the capabilities of a process/thread

The capset system call can be used to adjust the capability sets of a process/thread. The fundamental rule is that the permitted capability set is the superset of all current and future capability sets (until the thread execes a file).

  • Invariant: P(effective) <= P(permitted)
  • Invariant: P(inheritable) <= P(permitted)
  • Invariant: P'(permitted) <= P(permitted)

Here, P'(permitted) means the new value of the permitted capability set.

When execing a file

  • Invariant: P'(permitted) = (P(inheritable) & F(inheritable)) | (F(permitted) & cap_bset)
  • Invariant: P'(effective) = F(effective) ? P'(permitted) : 0
  • Invariant: P'(inheritable) = P(inheritable)

cap_bset denotes the process bounding capability set.

More

There are more invariants to enforce. I only summarize some of them as I read through Chapter 39 Capabilities, The Linux Programming Interface. I expect you to dive into the spec more deeply than I do to come up with a faithful and correct implementation.

Thanks! Get it. I will add a more correct implementation in the later PR(s).

@StanPlatinum StanPlatinum changed the title Add syscall capget/capset Add rudimental syscall capget/capset May 30, 2024
@StanPlatinum StanPlatinum marked this pull request as draft May 31, 2024 07:32
@StanPlatinum StanPlatinum marked this pull request as ready for review May 31, 2024 17:23
@StanPlatinum StanPlatinum force-pushed the dev-cap branch 2 times, most recently from b925779 to 8c8faac Compare June 4, 2024 07:08
Copy link
Contributor

@tatetian tatetian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for the contribution!

@tatetian tatetian merged commit 6e612fc into asterinas:main Jun 4, 2024
5 checks passed
@StanPlatinum StanPlatinum deleted the dev-cap branch June 4, 2024 12:38
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

Successfully merging this pull request may close these issues.

None yet

2 participants