Skip to content

Commit e4e48d4

Browse files
committed
capability prctls
1 parent baba947 commit e4e48d4

2 files changed

Lines changed: 64 additions & 11 deletions

File tree

kernel/interfaces/system/proc/cred.cppm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export namespace sched
101101

102102
inline constexpr bool cap_valid(cap_t cap)
103103
{
104-
return magic_enum::enum_contains(cap);
104+
return magic_enum::enum_flags_contains(cap);
105105
}
106106

107107
inline constexpr bool has_cap(cap_t set, cap_t cap)

kernel/source/system/syscall/misc.cpp

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import system.random;
1313
import system.chrono;
1414
import system.sched;
1515
import system.sysctl;
16+
import magic_enum;
1617

1718
namespace syscall::misc
1819
{
@@ -227,7 +228,7 @@ namespace syscall::misc
227228
unsigned long arg4, unsigned long arg5
228229
)
229230
{
230-
lib::unused(arg3, arg4, arg5);
231+
lib::unused(arg4, arg5);
231232
switch (option)
232233
{
233234
case 3: // PR_GET_DUMPABLE
@@ -243,15 +244,6 @@ namespace syscall::misc
243244
static_cast<sched::dumpable_t>(arg2), std::memory_order_relaxed
244245
);
245246
return 0;
246-
case 23: // PR_CAPBSET_READ
247-
{
248-
if (arg2 >= 64)
249-
return -EINVAL;
250-
const auto cap = static_cast<sched::cap_t>(1ul << arg2);
251-
if (!sched::cap_valid(cap))
252-
return -EINVAL;
253-
return sched::has_cap(sched::current_process()->cred->bounding, cap);
254-
}
255247
case 15: // PR_SET_NAME
256248
{
257249
constexpr std::size_t comm_max = 15;
@@ -287,6 +279,26 @@ namespace syscall::misc
287279
case 22: // PR_SET_SECCOMP
288280
// TODO
289281
return -EINVAL;
282+
case 23: // PR_CAPBSET_READ
283+
{
284+
if (arg2 >= 64)
285+
return -EINVAL;
286+
const auto cap = static_cast<sched::cap_t>(1ul << arg2);
287+
if (!sched::cap_valid(cap))
288+
return -EINVAL;
289+
return sched::has_cap(sched::current_process()->cred->bounding, cap);
290+
}
291+
case 24: // PR_CAPBSET_DROP
292+
{
293+
if (arg2 >= 64)
294+
return -EINVAL;
295+
const auto cap = static_cast<sched::cap_t>(1ul << arg2);
296+
if (!sched::cap_valid(cap))
297+
return -EINVAL;
298+
if (const auto ret = sched::cap_bounding_drop(cap); !ret)
299+
return -lib::map_error(ret.error());
300+
return 0;
301+
}
290302
case 38: // PR_SET_NO_NEW_PRIVS
291303
if (arg2 != 1)
292304
return -EINVAL;
@@ -295,6 +307,47 @@ namespace syscall::misc
295307
return 0;
296308
case 39: // PR_GET_NO_NEW_PRIVS
297309
return sched::current_process()->no_new_privs;
310+
case 47: // PR_CAP_AMBIENT
311+
switch (arg2)
312+
{
313+
case 1: // PR_CAP_AMBIENT_IS_SET
314+
{
315+
if (arg3 >= 64)
316+
return -EINVAL;
317+
const auto cap = static_cast<sched::cap_t>(1ul << arg3);
318+
if (!sched::cap_valid(cap))
319+
return -EINVAL;
320+
const auto ambient = sched::current_process()->cred->ambient;
321+
return sched::has_cap(ambient, cap);
322+
}
323+
case 2: // PR_CAP_AMBIENT_RAISE
324+
{
325+
if (arg3 >= 64)
326+
return -EINVAL;
327+
const auto cap = static_cast<sched::cap_t>(1ul << arg3);
328+
if (!sched::cap_valid(cap))
329+
return -EINVAL;
330+
if (const auto ret = sched::cap_ambient_raise(cap); !ret)
331+
return -lib::map_error(ret.error());
332+
return 0;
333+
}
334+
case 3: // PR_CAP_AMBIENT_LOWER
335+
{
336+
if (arg3 >= 64)
337+
return -EINVAL;
338+
const auto cap = static_cast<sched::cap_t>(1ul << arg3);
339+
if (!sched::cap_valid(cap))
340+
return -EINVAL;
341+
sched::cap_ambient_lower(cap);
342+
return 0;
343+
}
344+
case 4: // PR_CAP_AMBIENT_CLEAR_ALL
345+
sched::cap_ambient_lower(sched::cap_t::all);
346+
return 0;
347+
default:
348+
return -EINVAL;
349+
}
350+
std::unreachable();
298351
default:
299352
lib::error("prctl: unhandled option: 0x{:X}", option);
300353
return -EINVAL;

0 commit comments

Comments
 (0)