~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux-2.6.17/kernel/futex_compat.c

Version: ~ [ 2.6.16 ] ~ [ 2.6.17 ] ~
Architecture: ~ [ ia64 ] ~ [ i386 ] ~ [ arm ] ~ [ ppc ] ~ [ sparc64 ] ~

  1 /*
  2  * linux/kernel/futex_compat.c
  3  *
  4  * Futex compatibililty routines.
  5  *
  6  * Copyright 2006, Red Hat, Inc., Ingo Molnar
  7  */
  8 
  9 #include <linux/linkage.h>
 10 #include <linux/compat.h>
 11 #include <linux/futex.h>
 12 
 13 #include <asm/uaccess.h>
 14 
 15 /*
 16  * Walk curr->robust_list (very carefully, it's a userspace list!)
 17  * and mark any locks found there dead, and notify any waiters.
 18  *
 19  * We silently return on any sign of list-walking problem.
 20  */
 21 void compat_exit_robust_list(struct task_struct *curr)
 22 {
 23         struct compat_robust_list_head __user *head = curr->compat_robust_list;
 24         struct robust_list __user *entry, *pending;
 25         compat_uptr_t uentry, upending;
 26         unsigned int limit = ROBUST_LIST_LIMIT;
 27         compat_long_t futex_offset;
 28 
 29         /*
 30          * Fetch the list head (which was registered earlier, via
 31          * sys_set_robust_list()):
 32          */
 33         if (get_user(uentry, &head->list.next))
 34                 return;
 35         entry = compat_ptr(uentry);
 36         /*
 37          * Fetch the relative futex offset:
 38          */
 39         if (get_user(futex_offset, &head->futex_offset))
 40                 return;
 41         /*
 42          * Fetch any possibly pending lock-add first, and handle it
 43          * if it exists:
 44          */
 45         if (get_user(upending, &head->list_op_pending))
 46                 return;
 47         pending = compat_ptr(upending);
 48         if (upending)
 49                 handle_futex_death((void *)pending + futex_offset, curr);
 50 
 51         while (compat_ptr(uentry) != &head->list) {
 52                 /*
 53                  * A pending lock might already be on the list, so
 54                  * dont process it twice:
 55                  */
 56                 if (entry != pending)
 57                         if (handle_futex_death((void *)entry + futex_offset,
 58                                                 curr))
 59                                 return;
 60 
 61                 /*
 62                  * Fetch the next entry in the list:
 63                  */
 64                 if (get_user(uentry, (compat_uptr_t *)&entry->next))
 65                         return;
 66                 entry = compat_ptr(uentry);
 67                 /*
 68                  * Avoid excessively long or circular lists:
 69                  */
 70                 if (!--limit)
 71                         break;
 72 
 73                 cond_resched();
 74         }
 75 }
 76 
 77 asmlinkage long
 78 compat_sys_set_robust_list(struct compat_robust_list_head __user *head,
 79                            compat_size_t len)
 80 {
 81         if (unlikely(len != sizeof(*head)))
 82                 return -EINVAL;
 83 
 84         current->compat_robust_list = head;
 85 
 86         return 0;
 87 }
 88 
 89 asmlinkage long
 90 compat_sys_get_robust_list(int pid, compat_uptr_t *head_ptr,
 91                            compat_size_t __user *len_ptr)
 92 {
 93         struct compat_robust_list_head *head;
 94         unsigned long ret;
 95 
 96         if (!pid)
 97                 head = current->compat_robust_list;
 98         else {
 99                 struct task_struct *p;
100 
101                 ret = -ESRCH;
102                 read_lock(&tasklist_lock);
103                 p = find_task_by_pid(pid);
104                 if (!p)
105                         goto err_unlock;
106                 ret = -EPERM;
107                 if ((current->euid != p->euid) && (current->euid != p->uid) &&
108                                 !capable(CAP_SYS_PTRACE))
109                         goto err_unlock;
110                 head = p->compat_robust_list;
111                 read_unlock(&tasklist_lock);
112         }
113 
114         if (put_user(sizeof(*head), len_ptr))
115                 return -EFAULT;
116         return put_user(ptr_to_compat(head), head_ptr);
117 
118 err_unlock:
119         read_unlock(&tasklist_lock);
120 
121         return ret;
122 }
123 
124 asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
125                 struct compat_timespec __user *utime, u32 __user *uaddr2,
126                 u32 val3)
127 {
128         struct timespec t;
129         unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
130         int val2 = 0;
131 
132         if (utime && (op == FUTEX_WAIT)) {
133                 if (get_compat_timespec(&t, utime))
134                         return -EFAULT;
135                 if (!timespec_valid(&t))
136                         return -EINVAL;
137                 timeout = timespec_to_jiffies(&t) + 1;
138         }
139         if (op >= FUTEX_REQUEUE)
140                 val2 = (int) (unsigned long) utime;
141 
142         return do_futex((unsigned long)uaddr, op, val, timeout,
143                         (unsigned long)uaddr2, val2, val3);
144 }
145 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.