diff options
Diffstat (limited to 'kernel/capability.c')
| -rw-r--r-- | kernel/capability.c | 80 |
1 files changed, 46 insertions, 34 deletions
diff --git a/kernel/capability.c b/kernel/capability.c index b463871a4e69..0fcf1c14a297 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
| @@ -287,74 +287,84 @@ error: | |||
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | /** | 289 | /** |
| 290 | * has_capability - Does a task have a capability in init_user_ns | 290 | * has_ns_capability - Does a task have a capability in a specific user ns |
| 291 | * @t: The task in question | 291 | * @t: The task in question |
| 292 | * @ns: target user namespace | ||
| 292 | * @cap: The capability to be tested for | 293 | * @cap: The capability to be tested for |
| 293 | * | 294 | * |
| 294 | * Return true if the specified task has the given superior capability | 295 | * Return true if the specified task has the given superior capability |
| 295 | * currently in effect to the initial user namespace, false if not. | 296 | * currently in effect to the specified user namespace, false if not. |
| 296 | * | 297 | * |
| 297 | * Note that this does not set PF_SUPERPRIV on the task. | 298 | * Note that this does not set PF_SUPERPRIV on the task. |
| 298 | */ | 299 | */ |
| 299 | bool has_capability(struct task_struct *t, int cap) | 300 | bool has_ns_capability(struct task_struct *t, |
| 301 | struct user_namespace *ns, int cap) | ||
| 300 | { | 302 | { |
| 301 | int ret = security_real_capable(t, &init_user_ns, cap); | 303 | int ret; |
| 304 | |||
| 305 | rcu_read_lock(); | ||
| 306 | ret = security_capable(__task_cred(t), ns, cap); | ||
| 307 | rcu_read_unlock(); | ||
| 302 | 308 | ||
| 303 | return (ret == 0); | 309 | return (ret == 0); |
| 304 | } | 310 | } |
| 305 | 311 | ||
| 306 | /** | 312 | /** |
| 307 | * has_capability - Does a task have a capability in a specific user ns | 313 | * has_capability - Does a task have a capability in init_user_ns |
| 308 | * @t: The task in question | 314 | * @t: The task in question |
| 309 | * @ns: target user namespace | ||
| 310 | * @cap: The capability to be tested for | 315 | * @cap: The capability to be tested for |
| 311 | * | 316 | * |
| 312 | * Return true if the specified task has the given superior capability | 317 | * Return true if the specified task has the given superior capability |
| 313 | * currently in effect to the specified user namespace, false if not. | 318 | * currently in effect to the initial user namespace, false if not. |
| 314 | * | 319 | * |
| 315 | * Note that this does not set PF_SUPERPRIV on the task. | 320 | * Note that this does not set PF_SUPERPRIV on the task. |
| 316 | */ | 321 | */ |
| 317 | bool has_ns_capability(struct task_struct *t, | 322 | bool has_capability(struct task_struct *t, int cap) |
| 318 | struct user_namespace *ns, int cap) | ||
| 319 | { | 323 | { |
| 320 | int ret = security_real_capable(t, ns, cap); | 324 | return has_ns_capability(t, &init_user_ns, cap); |
| 321 | |||
| 322 | return (ret == 0); | ||
| 323 | } | 325 | } |
| 324 | 326 | ||
| 325 | /** | 327 | /** |
| 326 | * has_capability_noaudit - Does a task have a capability (unaudited) | 328 | * has_ns_capability_noaudit - Does a task have a capability (unaudited) |
| 329 | * in a specific user ns. | ||
| 327 | * @t: The task in question | 330 | * @t: The task in question |
| 331 | * @ns: target user namespace | ||
| 328 | * @cap: The capability to be tested for | 332 | * @cap: The capability to be tested for |
| 329 | * | 333 | * |
| 330 | * Return true if the specified task has the given superior capability | 334 | * Return true if the specified task has the given superior capability |
| 331 | * currently in effect to init_user_ns, false if not. Don't write an | 335 | * currently in effect to the specified user namespace, false if not. |
| 332 | * audit message for the check. | 336 | * Do not write an audit message for the check. |
| 333 | * | 337 | * |
| 334 | * Note that this does not set PF_SUPERPRIV on the task. | 338 | * Note that this does not set PF_SUPERPRIV on the task. |
| 335 | */ | 339 | */ |
| 336 | bool has_capability_noaudit(struct task_struct *t, int cap) | 340 | bool has_ns_capability_noaudit(struct task_struct *t, |
| 341 | struct user_namespace *ns, int cap) | ||
| 337 | { | 342 | { |
| 338 | int ret = security_real_capable_noaudit(t, &init_user_ns, cap); | 343 | int ret; |
| 344 | |||
| 345 | rcu_read_lock(); | ||
| 346 | ret = security_capable_noaudit(__task_cred(t), ns, cap); | ||
| 347 | rcu_read_unlock(); | ||
| 339 | 348 | ||
| 340 | return (ret == 0); | 349 | return (ret == 0); |
| 341 | } | 350 | } |
| 342 | 351 | ||
| 343 | /** | 352 | /** |
| 344 | * capable - Determine if the current task has a superior capability in effect | 353 | * has_capability_noaudit - Does a task have a capability (unaudited) in the |
| 354 | * initial user ns | ||
| 355 | * @t: The task in question | ||
| 345 | * @cap: The capability to be tested for | 356 | * @cap: The capability to be tested for |
| 346 | * | 357 | * |
| 347 | * Return true if the current task has the given superior capability currently | 358 | * Return true if the specified task has the given superior capability |
| 348 | * available for use, false if not. | 359 | * currently in effect to init_user_ns, false if not. Don't write an |
| 360 | * audit message for the check. | ||
| 349 | * | 361 | * |
| 350 | * This sets PF_SUPERPRIV on the task if the capability is available on the | 362 | * Note that this does not set PF_SUPERPRIV on the task. |
| 351 | * assumption that it's about to be used. | ||
| 352 | */ | 363 | */ |
| 353 | bool capable(int cap) | 364 | bool has_capability_noaudit(struct task_struct *t, int cap) |
| 354 | { | 365 | { |
| 355 | return ns_capable(&init_user_ns, cap); | 366 | return has_ns_capability_noaudit(t, &init_user_ns, cap); |
| 356 | } | 367 | } |
| 357 | EXPORT_SYMBOL(capable); | ||
| 358 | 368 | ||
| 359 | /** | 369 | /** |
| 360 | * ns_capable - Determine if the current task has a superior capability in effect | 370 | * ns_capable - Determine if the current task has a superior capability in effect |
| @@ -374,7 +384,7 @@ bool ns_capable(struct user_namespace *ns, int cap) | |||
| 374 | BUG(); | 384 | BUG(); |
| 375 | } | 385 | } |
| 376 | 386 | ||
| 377 | if (security_capable(ns, current_cred(), cap) == 0) { | 387 | if (has_ns_capability(current, ns, cap)) { |
| 378 | current->flags |= PF_SUPERPRIV; | 388 | current->flags |= PF_SUPERPRIV; |
| 379 | return true; | 389 | return true; |
| 380 | } | 390 | } |
| @@ -383,18 +393,20 @@ bool ns_capable(struct user_namespace *ns, int cap) | |||
| 383 | EXPORT_SYMBOL(ns_capable); | 393 | EXPORT_SYMBOL(ns_capable); |
| 384 | 394 | ||
| 385 | /** | 395 | /** |
| 386 | * task_ns_capable - Determine whether current task has a superior | 396 | * capable - Determine if the current task has a superior capability in effect |
| 387 | * capability targeted at a specific task's user namespace. | 397 | * @cap: The capability to be tested for |
| 388 | * @t: The task whose user namespace is targeted. | 398 | * |
| 389 | * @cap: The capability in question. | 399 | * Return true if the current task has the given superior capability currently |
| 400 | * available for use, false if not. | ||
| 390 | * | 401 | * |
| 391 | * Return true if it does, false otherwise. | 402 | * This sets PF_SUPERPRIV on the task if the capability is available on the |
| 403 | * assumption that it's about to be used. | ||
| 392 | */ | 404 | */ |
| 393 | bool task_ns_capable(struct task_struct *t, int cap) | 405 | bool capable(int cap) |
| 394 | { | 406 | { |
| 395 | return ns_capable(task_cred_xxx(t, user)->user_ns, cap); | 407 | return ns_capable(&init_user_ns, cap); |
| 396 | } | 408 | } |
| 397 | EXPORT_SYMBOL(task_ns_capable); | 409 | EXPORT_SYMBOL(capable); |
| 398 | 410 | ||
| 399 | /** | 411 | /** |
| 400 | * nsown_capable - Check superior capability to one's own user_ns | 412 | * nsown_capable - Check superior capability to one's own user_ns |
