lockdep: Provide off case for redundant_hardirqs_on increment
[safe/jmp/linux-2.6] / include / linux / cred.h
index b3c76e8..52507c3 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/capability.h>
 #include <linux/init.h>
 #include <linux/key.h>
+#include <linux/selinux.h>
 #include <asm/atomic.h>
 
 struct user_struct;
@@ -114,6 +115,13 @@ struct thread_group_cred {
  */
 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 */
@@ -143,7 +151,9 @@ struct cred {
 };
 
 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);
@@ -158,6 +168,46 @@ 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
@@ -187,6 +237,7 @@ static inline struct cred *get_new_cred(struct cred *cred)
 static inline const struct cred *get_cred(const struct cred *cred)
 {
        struct cred *nonconst_cred = (struct cred *) cred;
+       validate_creds(cred);
        return get_new_cred(nonconst_cred);
 }
 
@@ -205,7 +256,7 @@ static inline void put_cred(const struct cred *_cred)
 {
        struct cred *cred = (struct cred *) _cred;
 
-       BUG_ON(atomic_read(&(cred)->usage) <= 0);
+       validate_creds(cred);
        if (atomic_dec_and_test(&(cred)->usage))
                __put_cred(cred);
 }
@@ -229,7 +280,7 @@ static inline void put_cred(const struct cred *_cred)
  * task or by holding tasklist_lock to prevent it from being unlinked.
  */
 #define __task_cred(task) \
-       ((const struct cred *)(rcu_dereference((task)->real_cred)))
+       ((const struct cred *)(rcu_dereference_check((task)->real_cred, rcu_read_lock_held() || lockdep_tasklist_lock_is_held())))
 
 /**
  * get_task_cred - Get another task's objective credentials