Revert "Seperate read and write statistics of in_flight requests"
[safe/jmp/linux-2.6] / include / linux / cred.h
index 4221ec6..4e3387a 100644 (file)
@@ -1,4 +1,4 @@
-/* Credentials management
+/* Credentials management - see Documentation/credentials.txt
  *
  * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
 #define _LINUX_CRED_H
 
 #include <linux/capability.h>
+#include <linux/init.h>
 #include <linux/key.h>
+#include <linux/selinux.h>
 #include <asm/atomic.h>
 
 struct user_struct;
 struct cred;
+struct inode;
 
 /*
  * COW Supplementary groups list
@@ -59,6 +62,7 @@ do {                                                  \
 } while (0)
 
 extern struct group_info *groups_alloc(int);
+extern struct group_info init_groups;
 extern void groups_free(struct group_info *);
 extern int set_current_groups(struct group_info *);
 extern int set_groups(struct cred *, struct group_info *);
@@ -72,6 +76,21 @@ extern int in_group_p(gid_t);
 extern int in_egroup_p(gid_t);
 
 /*
+ * The common credentials for a thread group
+ * - shared by CLONE_THREAD
+ */
+#ifdef CONFIG_KEYS
+struct thread_group_cred {
+       atomic_t        usage;
+       pid_t           tgid;                   /* thread group process ID */
+       spinlock_t      lock;
+       struct key      *session_keyring;       /* keyring inherited over fork */
+       struct key      *process_keyring;       /* keyring private to this process */
+       struct rcu_head rcu;                    /* RCU deletion hook */
+};
+#endif
+
+/*
  * The security context of a task
  *
  * The parts of the context break down into two categories:
@@ -96,6 +115,13 @@ extern int in_egroup_p(gid_t);
  */
 struct cred {
        atomic_t        usage;
+#ifdef CONFIG_DEBUG_CREDENTIALS
+       atomic_t        subscribers;    /* number of processes subscribed */
+       void            *put_addr;
+       unsigned        magic;
+#define CRED_MAGIC     0x43736564
+#define CRED_MAGIC_DEAD        0x44656144
+#endif
        uid_t           uid;            /* real UID of the task */
        gid_t           gid;            /* real GID of the task */
        uid_t           suid;           /* saved UID of the task */
@@ -114,6 +140,7 @@ struct cred {
                                         * keys to */
        struct key      *thread_keyring; /* keyring private to this thread */
        struct key      *request_key_auth; /* assumed request_key authority */
+       struct thread_group_cred *tgcred; /* thread-group shared credentials */
 #endif
 #ifdef CONFIG_SECURITY
        void            *security;      /* subjective LSM security */
@@ -121,11 +148,78 @@ struct cred {
        struct user_struct *user;       /* real user ID subscription */
        struct group_info *group_info;  /* supplementary groups for euid/fsgid */
        struct rcu_head rcu;            /* RCU deletion hook */
-       spinlock_t      lock;           /* lock for pointer changes */
 };
 
 extern void __put_cred(struct cred *);
+extern void exit_creds(struct task_struct *);
 extern int copy_creds(struct task_struct *, unsigned long);
+extern struct cred *cred_alloc_blank(void);
+extern struct cred *prepare_creds(void);
+extern struct cred *prepare_exec_creds(void);
+extern struct cred *prepare_usermodehelper_creds(void);
+extern int commit_creds(struct cred *);
+extern void abort_creds(struct cred *);
+extern const struct cred *override_creds(const struct cred *);
+extern void revert_creds(const struct cred *);
+extern struct cred *prepare_kernel_cred(struct task_struct *);
+extern int change_create_files_as(struct cred *, struct inode *);
+extern int set_security_override(struct cred *, u32);
+extern int set_security_override_from_ctx(struct cred *, const char *);
+extern int set_create_files_as(struct cred *, struct inode *);
+extern void __init cred_init(void);
+
+/*
+ * check for validity of credentials
+ */
+#ifdef CONFIG_DEBUG_CREDENTIALS
+extern void __invalid_creds(const struct cred *, const char *, unsigned);
+extern void __validate_process_creds(struct task_struct *,
+                                    const char *, unsigned);
+
+extern bool creds_are_invalid(const struct cred *cred);
+
+static inline void __validate_creds(const struct cred *cred,
+                                   const char *file, unsigned line)
+{
+       if (unlikely(creds_are_invalid(cred)))
+               __invalid_creds(cred, file, line);
+}
+
+#define validate_creds(cred)                           \
+do {                                                   \
+       __validate_creds((cred), __FILE__, __LINE__);   \
+} while(0)
+
+#define validate_process_creds()                               \
+do {                                                           \
+       __validate_process_creds(current, __FILE__, __LINE__);  \
+} while(0)
+
+extern void validate_creds_for_do_exit(struct task_struct *);
+#else
+static inline void validate_creds(const struct cred *cred)
+{
+}
+static inline void validate_creds_for_do_exit(struct task_struct *tsk)
+{
+}
+static inline void validate_process_creds(void)
+{
+}
+#endif
+
+/**
+ * get_new_cred - Get a reference on a new set of credentials
+ * @cred: The new credentials to reference
+ *
+ * Get a reference on the specified set of new credentials.  The caller must
+ * release the reference.
+ */
+static inline struct cred *get_new_cred(struct cred *cred)
+{
+       atomic_inc(&cred->usage);
+       return cred;
+}
 
 /**
  * get_cred - Get a reference on a set of credentials
@@ -133,11 +227,18 @@ extern int copy_creds(struct task_struct *, unsigned long);
  *
  * Get a reference on the specified set of credentials.  The caller must
  * release the reference.
+ *
+ * This is used to deal with a committed set of credentials.  Although the
+ * pointer is const, this will temporarily discard the const and increment the
+ * usage count.  The purpose of this is to attempt to catch at compile time the
+ * accidental alteration of a set of credentials that should be considered
+ * immutable.
  */
-static inline struct cred *get_cred(struct cred *cred)
+static inline const struct cred *get_cred(const struct cred *cred)
 {
-       atomic_inc(&cred->usage);
-       return cred;
+       struct cred *nonconst_cred = (struct cred *) cred;
+       validate_creds(cred);
+       return get_new_cred(nonconst_cred);
 }
 
 /**
@@ -146,40 +247,47 @@ static inline struct cred *get_cred(struct cred *cred)
  *
  * Release a reference to a set of credentials, deleting them when the last ref
  * is released.
+ *
+ * This takes a const pointer to a set of credentials because the credentials
+ * on task_struct are attached by const pointers to prevent accidental
+ * alteration of otherwise immutable credential sets.
  */
-static inline void put_cred(struct cred *cred)
+static inline void put_cred(const struct cred *_cred)
 {
+       struct cred *cred = (struct cred *) _cred;
+
+       validate_creds(cred);
        if (atomic_dec_and_test(&(cred)->usage))
                __put_cred(cred);
 }
 
 /**
- * current_cred - Access the current task's credentials
+ * current_cred - Access the current task's subjective credentials
  *
- * Access the credentials of the current task.
+ * Access the subjective credentials of the current task.
  */
 #define current_cred() \
        (current->cred)
 
 /**
- * __task_cred - Access another task's credentials
+ * __task_cred - Access a task's objective credentials
  * @task: The task to query
  *
- * Access the credentials of another task.  The caller must hold the
- * RCU readlock.
+ * Access the objective credentials of a task.  The caller must hold the RCU
+ * readlock.
  *
  * The caller must make sure task doesn't go away, either by holding a ref on
  * task or by holding tasklist_lock to prevent it from being unlinked.
  */
 #define __task_cred(task) \
-       ((const struct cred *)(rcu_dereference((task)->cred)))
+       ((const struct cred *)(rcu_dereference((task)->real_cred)))
 
 /**
- * get_task_cred - Get another task's credentials
+ * get_task_cred - Get another task's objective credentials
  * @task: The task to query
  *
- * Get the credentials of a task, pinning them so that they can't go away.
- * Accessing a task's credentials directly is not permitted.
+ * Get the objective credentials of a task, pinning them so that they can't go
+ * away.  Accessing a task's credentials directly is not permitted.
  *
  * The caller must make sure task doesn't go away, either by holding a ref on
  * task or by holding tasklist_lock to prevent it from being unlinked.
@@ -195,10 +303,11 @@ static inline void put_cred(struct cred *cred)
 })
 
 /**
- * get_current_cred - Get the current task's credentials
+ * get_current_cred - Get the current task's subjective credentials
  *
- * Get the credentials of the current task, pinning them so that they can't go
- * away.  Accessing the current task's credentials directly is not permitted.
+ * Get the subjective credentials of the current task, pinning them so that
+ * they can't go away.  Accessing the current task's credentials directly is
+ * not permitted.
  */
 #define get_current_cred()                             \
        (get_cred(current_cred()))
@@ -233,13 +342,13 @@ static inline void put_cred(struct cred *cred)
        __groups;                                       \
 })
 
-#define task_cred_xxx(task, xxx)               \
-({                                             \
-       __typeof__(task->cred->xxx) ___val;     \
-       rcu_read_lock();                        \
-       ___val = __task_cred((task))->xxx;      \
-       rcu_read_unlock();                      \
-       ___val;                                 \
+#define task_cred_xxx(task, xxx)                       \
+({                                                     \
+       __typeof__(((struct cred *)NULL)->xxx) ___val;  \
+       rcu_read_lock();                                \
+       ___val = __task_cred((task))->xxx;              \
+       rcu_read_unlock();                              \
+       ___val;                                         \
 })
 
 #define task_uid(task)         (task_cred_xxx((task), uid))
@@ -260,6 +369,7 @@ static inline void put_cred(struct cred *cred)
 #define current_fsgid()        (current_cred_xxx(fsgid))
 #define current_cap()          (current_cred_xxx(cap_effective))
 #define current_user()         (current_cred_xxx(user))
+#define current_user_ns()      (current_cred_xxx(user)->user_ns)
 #define current_security()     (current_cred_xxx(security))
 
 #define current_uid_gid(_uid, _gid)            \