Lines Matching full:filter

39 #include <linux/filter.h>
62 /* The struct pid of the task whose filter triggered the notification */
65 /* The "cookie" for this request; this is unique for this filter. */
143 * filter->notify_lock.
158 * struct action_cache - per-filter cache of seccomp actions per
162 * filter will always allow the syscall, for the
165 * filter will always allow the syscall, for the
192 * A filter's reference count is incremented for each directly
193 * attached task, once for the dependent filter, and if
195 * the filter can be freed.
196 * @users: A filter's @users count is incremented for each directly
197 * attached task (filter installation, fork(), thread_sync),
198 * and once for the dependent filter (tracked in filter->prev).
200 * users of that filter exist. No new tasks can get associated with
201 * this filter after reaching 0. The @users count is always smaller
203 * the filter can be freed.
208 * @prev: points to a previously installed, or inherited, filter
216 * with current->seccomp.filter, the most recently attached or inherited filter.
267 * seccomp_check_filter - verify seccomp filter code
268 * @filter: filter to verify
269 * @flen: length of filter
271 * Takes a previously checked filter (by bpf_check_classic) and
272 * redirects all filter code that loads struct sk_buff data
278 static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen) in seccomp_check_filter() argument
282 struct sock_filter *ftest = &filter[pc]; in seccomp_check_filter()
362 * @sfilter: The seccomp filter
399 * unless filter returned SECCOMP_RET_ALLOW, in which case it will
408 /* Make sure cross-thread synced filter points somewhere sane. */ in seccomp_run_filters()
410 READ_ONCE(current->seccomp.filter); in seccomp_run_filters()
456 * filter) is set. in seccomp_assign_mode()
486 * seccomp filter.
509 is_ancestor(thread->seccomp.filter, in seccomp_can_sync_threads()
510 caller->seccomp.filter))) in seccomp_can_sync_threads()
524 static inline void seccomp_filter_free(struct seccomp_filter *filter) in seccomp_filter_free() argument
526 if (filter) { in seccomp_filter_free()
527 bpf_prog_destroy(filter->prog); in seccomp_filter_free()
528 kfree(filter); in seccomp_filter_free()
553 /* Notify about any unused filters in the task's former filter tree. */ in __seccomp_filter_release()
560 * seccomp_filter_release - Detach the task from its filter tree,
564 * @tsk: task the filter should be released from.
567 * it detaches it from its filter tree. PF_EXITING has to be set
578 orig = tsk->seccomp.filter; in seccomp_filter_release()
579 /* Detach task from its filter tree. */ in seccomp_filter_release()
580 tsk->seccomp.filter = NULL; in seccomp_filter_release()
586 * seccomp_sync_threads: sets all threads to use current's filter
624 __seccomp_filter_release(thread->seccomp.filter); in seccomp_sync_threads()
626 /* Make our new filter tree visible. */ in seccomp_sync_threads()
627 smp_store_release(&thread->seccomp.filter, in seccomp_sync_threads()
628 caller->seccomp.filter); in seccomp_sync_threads()
654 * seccomp_prepare_filter: Prepares a seccomp filter for use.
657 * Returns filter on success or an ERR_PTR on failure.
676 * Installing a seccomp filter requires that the task has in seccomp_prepare_filter()
715 struct seccomp_filter *filter = ERR_PTR(-EFAULT); in seccomp_prepare_user_filter() local
723 fprog.filter = compat_ptr(fprog32.filter); in seccomp_prepare_user_filter()
728 filter = seccomp_prepare_filter(&fprog); in seccomp_prepare_user_filter()
730 return filter; in seccomp_prepare_user_filter()
735 * seccomp_is_const_allow - check if filter is constant allow with given data
760 struct sock_filter *insn = &fprog->filter[pc]; in seccomp_is_const_allow()
817 /* ran off the end of the filter?! */ in seccomp_is_const_allow()
831 /* The new filter must be as restrictive as the last. */ in seccomp_cache_prepare_bitmap()
852 * atomic clear_bit() not needed, filter not visible yet. in seccomp_cache_prepare_bitmap()
859 * seccomp_cache_prepare - emulate the filter to find cacheable syscalls
860 * @sfilter: The seccomp filter
885 * seccomp_attach_filter: validate and attach filter
886 * @flags: flags to change filter behavior
887 * @filter: seccomp filter to add to the current process
893 * seccomp mode or did not have an ancestral seccomp filter
897 struct seccomp_filter *filter) in seccomp_attach_filter() argument
904 /* Validate resulting filter length. */ in seccomp_attach_filter()
905 total_insns = filter->prog->len; in seccomp_attach_filter()
906 for (walker = current->seccomp.filter; walker; walker = walker->prev) in seccomp_attach_filter()
926 filter->log = true; in seccomp_attach_filter()
930 filter->wait_killable_recv = true; in seccomp_attach_filter()
933 * If there is an existing filter, make it the prev and don't drop its in seccomp_attach_filter()
936 filter->prev = current->seccomp.filter; in seccomp_attach_filter()
937 seccomp_cache_prepare(filter); in seccomp_attach_filter()
938 current->seccomp.filter = filter; in seccomp_attach_filter()
941 /* Now that the new filter is in place, synchronize to all threads. */ in seccomp_attach_filter()
948 static void __get_seccomp_filter(struct seccomp_filter *filter) in __get_seccomp_filter() argument
950 refcount_inc(&filter->refs); in __get_seccomp_filter()
953 /* get_seccomp_filter - increments the reference count of the filter on @tsk */
956 struct seccomp_filter *orig = tsk->seccomp.filter; in get_seccomp_filter()
1086 static u64 seccomp_next_notify_id(struct seccomp_filter *filter) in seccomp_next_notify_id() argument
1090 * filter. in seccomp_next_notify_id()
1092 lockdep_assert_held(&filter->notify_lock); in seccomp_next_notify_id()
1093 return filter->notif->next_id++; in seccomp_next_notify_id()
1269 /* Let the filter pass back 16 bits of data. */ in __seccomp_filter()
1328 * Note that the "match" filter will always be NULL for in __seccomp_filter()
1432 static void seccomp_notify_free(struct seccomp_filter *filter) in seccomp_notify_free() argument
1434 kfree(filter->notif); in seccomp_notify_free()
1435 filter->notif = NULL; in seccomp_notify_free()
1438 static void seccomp_notify_detach(struct seccomp_filter *filter) in seccomp_notify_detach() argument
1442 if (!filter) in seccomp_notify_detach()
1445 mutex_lock(&filter->notify_lock); in seccomp_notify_detach()
1451 list_for_each_entry(knotif, &filter->notif->notifications, list) { in seccomp_notify_detach()
1467 seccomp_notify_free(filter); in seccomp_notify_detach()
1468 mutex_unlock(&filter->notify_lock); in seccomp_notify_detach()
1473 struct seccomp_filter *filter = file->private_data; in seccomp_notify_release() local
1475 seccomp_notify_detach(filter); in seccomp_notify_release()
1476 __put_seccomp_filter(filter); in seccomp_notify_release()
1482 find_notification(struct seccomp_filter *filter, u64 id) in find_notification() argument
1486 lockdep_assert_held(&filter->notify_lock); in find_notification()
1488 list_for_each_entry(cur, &filter->notif->notifications, list) { in find_notification()
1505 static int recv_wait_event(struct seccomp_filter *filter) in recv_wait_event() argument
1510 if (refcount_read(&filter->users) == 0) in recv_wait_event()
1513 if (atomic_dec_if_positive(&filter->notif->requests) >= 0) in recv_wait_event()
1517 ret = prepare_to_wait_event(&filter->wqh, &wait, TASK_INTERRUPTIBLE); in recv_wait_event()
1519 if (atomic_dec_if_positive(&filter->notif->requests) >= 0) in recv_wait_event()
1521 if (refcount_read(&filter->users) == 0) in recv_wait_event()
1529 finish_wait(&filter->wqh, &wait); in recv_wait_event()
1533 static long seccomp_notify_recv(struct seccomp_filter *filter, in seccomp_notify_recv() argument
1549 ret = recv_wait_event(filter); in seccomp_notify_recv()
1553 mutex_lock(&filter->notify_lock); in seccomp_notify_recv()
1554 list_for_each_entry(cur, &filter->notif->notifications, list) { in seccomp_notify_recv()
1576 wake_up_poll(&filter->wqh, EPOLLOUT | EPOLLWRNORM); in seccomp_notify_recv()
1579 mutex_unlock(&filter->notify_lock); in seccomp_notify_recv()
1590 mutex_lock(&filter->notify_lock); in seccomp_notify_recv()
1591 knotif = find_notification(filter, unotif.id); in seccomp_notify_recv()
1594 if (should_sleep_killable(filter, knotif)) in seccomp_notify_recv()
1597 atomic_inc(&filter->notif->requests); in seccomp_notify_recv()
1598 wake_up_poll(&filter->wqh, EPOLLIN | EPOLLRDNORM); in seccomp_notify_recv()
1600 mutex_unlock(&filter->notify_lock); in seccomp_notify_recv()
1606 static long seccomp_notify_send(struct seccomp_filter *filter, in seccomp_notify_send() argument
1623 ret = mutex_lock_interruptible(&filter->notify_lock); in seccomp_notify_send()
1627 knotif = find_notification(filter, resp.id); in seccomp_notify_send()
1644 if (filter->notif->flags & SECCOMP_USER_NOTIF_FD_SYNC_WAKE_UP) in seccomp_notify_send()
1649 mutex_unlock(&filter->notify_lock); in seccomp_notify_send()
1653 static long seccomp_notify_id_valid(struct seccomp_filter *filter, in seccomp_notify_id_valid() argument
1663 ret = mutex_lock_interruptible(&filter->notify_lock); in seccomp_notify_id_valid()
1667 knotif = find_notification(filter, id); in seccomp_notify_id_valid()
1673 mutex_unlock(&filter->notify_lock); in seccomp_notify_id_valid()
1677 static long seccomp_notify_set_flags(struct seccomp_filter *filter, in seccomp_notify_set_flags() argument
1685 ret = mutex_lock_interruptible(&filter->notify_lock); in seccomp_notify_set_flags()
1688 filter->notif->flags = flags; in seccomp_notify_set_flags()
1689 mutex_unlock(&filter->notify_lock); in seccomp_notify_set_flags()
1693 static long seccomp_notify_addfd(struct seccomp_filter *filter, in seccomp_notify_addfd() argument
1731 ret = mutex_lock_interruptible(&filter->notify_lock); in seccomp_notify_addfd()
1735 knotif = find_notification(filter, addfd.id); in seccomp_notify_addfd()
1770 mutex_unlock(&filter->notify_lock); in seccomp_notify_addfd()
1786 mutex_lock(&filter->notify_lock); in seccomp_notify_addfd()
1800 mutex_unlock(&filter->notify_lock); in seccomp_notify_addfd()
1810 struct seccomp_filter *filter = file->private_data; in seccomp_notify_ioctl() local
1816 return seccomp_notify_recv(filter, buf); in seccomp_notify_ioctl()
1818 return seccomp_notify_send(filter, buf); in seccomp_notify_ioctl()
1821 return seccomp_notify_id_valid(filter, buf); in seccomp_notify_ioctl()
1823 return seccomp_notify_set_flags(filter, arg); in seccomp_notify_ioctl()
1830 return seccomp_notify_addfd(filter, buf, _IOC_SIZE(cmd)); in seccomp_notify_ioctl()
1839 struct seccomp_filter *filter = file->private_data; in seccomp_notify_poll() local
1843 poll_wait(file, &filter->wqh, poll_tab); in seccomp_notify_poll()
1845 if (mutex_lock_interruptible(&filter->notify_lock) < 0) in seccomp_notify_poll()
1848 list_for_each_entry(cur, &filter->notif->notifications, list) { in seccomp_notify_poll()
1857 mutex_unlock(&filter->notify_lock); in seccomp_notify_poll()
1859 if (refcount_read(&filter->users) == 0) in seccomp_notify_poll()
1872 static struct file *init_listener(struct seccomp_filter *filter) in init_listener() argument
1877 filter->notif = kzalloc(sizeof(*(filter->notif)), GFP_KERNEL); in init_listener()
1878 if (!filter->notif) in init_listener()
1881 filter->notif->next_id = get_random_u64(); in init_listener()
1882 INIT_LIST_HEAD(&filter->notif->notifications); in init_listener()
1885 filter, O_RDWR); in init_listener()
1890 __get_seccomp_filter(filter); in init_listener()
1894 seccomp_notify_free(filter); in init_listener()
1901 * If so, we'll want to reject this filter.
1905 * we use current->seccomp.filter.
1916 for (cur = current->seccomp.filter; cur; cur = cur->prev) { in has_duplicate_listener()
1925 * seccomp_set_mode_filter: internal function for setting seccomp filter
1926 * @flags: flags to change filter behavior
1927 * @filter: struct sock_fprog containing filter
1930 * Every filter successfully installed will be evaluated (in reverse order)
1938 const char __user *filter) in seccomp_set_mode_filter() argument
1970 /* Prepare the new filter before holding any locks. */ in seccomp_set_mode_filter()
1971 prepared = seccomp_prepare_user_filter(filter); in seccomp_set_mode_filter()
2011 /* Do not free the successfully attached filter. */ in seccomp_set_mode_filter()
2037 const char __user *filter) in seccomp_set_mode_filter() argument
2116 * @filter: optional struct sock_fprog for use with SECCOMP_MODE_FILTER
2120 long prctl_set_seccomp(unsigned long seccomp_mode, void __user *filter) in prctl_set_seccomp() argument
2129 * Setting strict mode through prctl always ignored filter, in prctl_set_seccomp()
2137 uargs = filter; in prctl_set_seccomp()
2151 struct seccomp_filter *orig, *filter; in get_nth_filter() local
2165 orig = task->seccomp.filter; in get_nth_filter()
2170 for (filter = orig; filter; filter = filter->prev) in get_nth_filter()
2174 filter = ERR_PTR(-ENOENT); in get_nth_filter()
2179 for (filter = orig; filter && count > 1; filter = filter->prev) in get_nth_filter()
2182 if (WARN_ON(count != 1 || !filter)) { in get_nth_filter()
2183 filter = ERR_PTR(-ENOENT); in get_nth_filter()
2187 __get_seccomp_filter(filter); in get_nth_filter()
2191 return filter; in get_nth_filter()
2197 struct seccomp_filter *filter; in seccomp_get_filter() local
2206 filter = get_nth_filter(task, filter_off); in seccomp_get_filter()
2207 if (IS_ERR(filter)) in seccomp_get_filter()
2208 return PTR_ERR(filter); in seccomp_get_filter()
2210 fprog = filter->prog->orig_prog; in seccomp_get_filter()
2212 /* This must be a new non-cBPF filter, since we save in seccomp_get_filter()
2213 * every cBPF filter's orig_prog above when in seccomp_get_filter()
2224 if (copy_to_user(data, fprog->filter, bpf_classic_proglen(fprog))) in seccomp_get_filter()
2228 __put_seccomp_filter(filter); in seccomp_get_filter()
2236 struct seccomp_filter *filter; in seccomp_get_metadata() local
2252 filter = get_nth_filter(task, kmd.filter_off); in seccomp_get_metadata()
2253 if (IS_ERR(filter)) in seccomp_get_metadata()
2254 return PTR_ERR(filter); in seccomp_get_metadata()
2256 if (filter->log) in seccomp_get_metadata()
2263 __put_seccomp_filter(filter); in seccomp_get_metadata()
2505 char *status = cached ? "ALLOW" : "FILTER"; in device_initcall()
2527 f = READ_ONCE(task->seccomp.filter); in proc_pid_seccomp_cache()
2533 /* prevent filter from being freed while we are printing it */ in proc_pid_seccomp_cache()