History

Merge tag 'fsnotify_for_v6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull fsnotify updates from Jan Kara: "Support for auditing decisions regarding fanotify permission events" * tag 'fsnotify_for_v6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: fanotify,audit: Allow audit to use the full permission event response fanotify: define struct members to hold response decision context fanotify: Ensure consistent variable type for response

Linus Torvalds committed 3 years ago

Commit cd776a42 parents 6639c3c 032bffd7 files · +131 −33Browse files

Unified · Split

7 files
  1. fs/notify/fanotify/fanotify.c +6 −2
  2. fs/notify/fanotify/fanotify.h +5 −1
  3. fs/notify/fanotify/fanotify_user.c +66 −22
  4. include/linux/audit.h +5 −4
  5. include/linux/fanotify.h +5 −0
  6. include/uapi/linux/fanotify.h +29 −1
  7. kernel/auditsc.c +15 −3
fs/notify/fanotify/fanotify.c+6−2
@@ -262,7 +262,7 @@ static int fanotify_get_response(struct fsnotify_group *group, · 261 unmodified lines
262 }262 }
263 263
264 /* userspace responded, convert to something usable */264 /* userspace responded, convert to something usable */
265 switch (event->response & ~FAN_AUDIT) {265 switch (event->response & FANOTIFY_RESPONSE_ACCESS) {
266 case FAN_ALLOW:266 case FAN_ALLOW:
267 ret = 0;267 ret = 0;
268 break;268 break;
@@ -273,7 +273,8 @@ static int fanotify_get_response(struct fsnotify_group *group, · 4 unmodified lines
273 273
274 /* Check if the response should be audited */274 /* Check if the response should be audited */
275 if (event->response & FAN_AUDIT)275 if (event->response & FAN_AUDIT)
276 audit_fanotify(event->response & ~FAN_AUDIT);276 audit_fanotify(event->response & ~FAN_AUDIT,
277 &event->audit_rule);
277 278
278 pr_debug("%s: group=%p event=%p about to return ret=%d\n", __func__,279 pr_debug("%s: group=%p event=%p about to return ret=%d\n", __func__,
279 group, event, ret);280 group, event, ret);
@@ -563,6 +564,9 @@ static struct fanotify_event *fanotify_alloc_perm_event(const struct path *path, · 283 unmodified lines
563 564
564 pevent->fae.type = FANOTIFY_EVENT_TYPE_PATH_PERM;565 pevent->fae.type = FANOTIFY_EVENT_TYPE_PATH_PERM;
565 pevent->response = 0;566 pevent->response = 0;
567 pevent->hdr.type = FAN_RESPONSE_INFO_NONE;
568 pevent->hdr.pad = 0;
569 pevent->hdr.len = 0;
566 pevent->state = FAN_EVENT_INIT;570 pevent->state = FAN_EVENT_INIT;
567 pevent->path = *path;571 pevent->path = *path;
568 path_get(path);572 path_get(path);
fs/notify/fanotify/fanotify.h+5−1
@@ -425,9 +425,13 @@ FANOTIFY_PE(struct fanotify_event *event) · 424 unmodified lines
425struct fanotify_perm_event {425struct fanotify_perm_event {
426 struct fanotify_event fae;426 struct fanotify_event fae;
427 struct path path;427 struct path path;
428 unsigned short response; /* userspace answer to the event */428 u32 response; /* userspace answer to the event */
429 unsigned short state; /* state of the event */429 unsigned short state; /* state of the event */
430 int fd; /* fd we passed to userspace for this event */430 int fd; /* fd we passed to userspace for this event */
431 union {
432 struct fanotify_response_info_header hdr;
433 struct fanotify_response_info_audit_rule audit_rule;
434 };
431};435};
432 436
433static inline struct fanotify_perm_event *437static inline struct fanotify_perm_event *
fs/notify/fanotify/fanotify_user.c+66−22
@@ -283,19 +283,42 @@ static int create_fd(struct fsnotify_group *group, const struct path *path, · 282 unmodified lines
283 return client_fd;283 return client_fd;
284}284}
285 285
286static int process_access_response_info(const char __user *info,
287 size_t info_len,
288 struct fanotify_response_info_audit_rule *friar)
289{
290 if (info_len != sizeof(*friar))
291 return -EINVAL;
292
293 if (copy_from_user(friar, info, sizeof(*friar)))
294 return -EFAULT;
295
296 if (friar->hdr.type != FAN_RESPONSE_INFO_AUDIT_RULE)
297 return -EINVAL;
298 if (friar->hdr.pad != 0)
299 return -EINVAL;
300 if (friar->hdr.len != sizeof(*friar))
301 return -EINVAL;
302
303 return info_len;
304}
305
286/*306/*
287 * Finish processing of permission event by setting it to ANSWERED state and307 * Finish processing of permission event by setting it to ANSWERED state and
288 * drop group->notification_lock.308 * drop group->notification_lock.
289 */309 */
290static void finish_permission_event(struct fsnotify_group *group,310static void finish_permission_event(struct fsnotify_group *group,
291 struct fanotify_perm_event *event,311 struct fanotify_perm_event *event, u32 response,
292 unsigned int response)312 struct fanotify_response_info_audit_rule *friar)
293 __releases(&group->notification_lock)313 __releases(&group->notification_lock)
294{314{
295 bool destroy = false;315 bool destroy = false;
296 316
297 assert_spin_locked(&group->notification_lock);317 assert_spin_locked(&group->notification_lock);
298 event->response = response;318 event->response = response & ~FAN_INFO;
319 if (response & FAN_INFO)
320 memcpy(&event->audit_rule, friar, sizeof(*friar));
321
299 if (event->state == FAN_EVENT_CANCELED)322 if (event->state == FAN_EVENT_CANCELED)
300 destroy = true;323 destroy = true;
301 else324 else
@@ -306,20 +329,27 @@ static void finish_permission_event(struct fsnotify_group *group, · 4 unmodified lines
306}329}
307 330
308static int process_access_response(struct fsnotify_group *group,331static int process_access_response(struct fsnotify_group *group,
309 struct fanotify_response *response_struct)332 struct fanotify_response *response_struct,
333 const char __user *info,
334 size_t info_len)
310{335{
311 struct fanotify_perm_event *event;336 struct fanotify_perm_event *event;
312 int fd = response_struct->fd;337 int fd = response_struct->fd;
313 int response = response_struct->response;338 u32 response = response_struct->response;
339 int ret = info_len;
340 struct fanotify_response_info_audit_rule friar;
314 341
315 pr_debug("%s: group=%p fd=%d response=%d\n", __func__, group,342 pr_debug("%s: group=%p fd=%d response=%u buf=%p size=%zu\n", __func__,
316 fd, response);343 group, fd, response, info, info_len);
317 /*344 /*
318 * make sure the response is valid, if invalid we do nothing and either345 * make sure the response is valid, if invalid we do nothing and either
319 * userspace can send a valid response or we will clean it up after the346 * userspace can send a valid response or we will clean it up after the
320 * timeout347 * timeout
321 */348 */
322 switch (response & ~FAN_AUDIT) {349 if (response & ~FANOTIFY_RESPONSE_VALID_MASK)
350 return -EINVAL;
351
352 switch (response & FANOTIFY_RESPONSE_ACCESS) {
323 case FAN_ALLOW:353 case FAN_ALLOW:
324 case FAN_DENY:354 case FAN_DENY:
325 break;355 break;
@@ -327,10 +357,20 @@ static int process_access_response(struct fsnotify_group *group, · 1 unmodified line
327 return -EINVAL;357 return -EINVAL;
328 }358 }
329 359
330 if (fd < 0)360 if ((response & FAN_AUDIT) && !FAN_GROUP_FLAG(group, FAN_ENABLE_AUDIT))
331 return -EINVAL;361 return -EINVAL;
332 362
333 if ((response & FAN_AUDIT) && !FAN_GROUP_FLAG(group, FAN_ENABLE_AUDIT))363 if (response & FAN_INFO) {
364 ret = process_access_response_info(info, info_len, &friar);
365 if (ret < 0)
366 return ret;
367 if (fd == FAN_NOFD)
368 return ret;
369 } else {
370 ret = 0;
371 }
372
373 if (fd < 0)
334 return -EINVAL;374 return -EINVAL;
335 375
336 spin_lock(&group->notification_lock);376 spin_lock(&group->notification_lock);
@@ -340,9 +380,9 @@ static int process_access_response(struct fsnotify_group *group, · 3 unmodified lines
340 continue;380 continue;
341 381
342 list_del_init(&event->fae.fse.list);382 list_del_init(&event->fae.fse.list);
343 finish_permission_event(group, event, response);383 finish_permission_event(group, event, response, &friar);
344 wake_up(&group->fanotify_data.access_waitq);384 wake_up(&group->fanotify_data.access_waitq);
345 return 0;385 return ret;
346 }386 }
347 spin_unlock(&group->notification_lock);387 spin_unlock(&group->notification_lock);
348 388
@@ -804,7 +844,7 @@ static ssize_t fanotify_read(struct file *file, char __user *buf, · 455 unmodified lines
804 if (ret <= 0) {844 if (ret <= 0) {
805 spin_lock(&group->notification_lock);845 spin_lock(&group->notification_lock);
806 finish_permission_event(group,846 finish_permission_event(group,
807 FANOTIFY_PERM(event), FAN_DENY);847 FANOTIFY_PERM(event), FAN_DENY, NULL);
808 wake_up(&group->fanotify_data.access_waitq);848 wake_up(&group->fanotify_data.access_waitq);
809 } else {849 } else {
810 spin_lock(&group->notification_lock);850 spin_lock(&group->notification_lock);
@@ -827,28 +867,32 @@ static ssize_t fanotify_read(struct file *file, char __user *buf, · 16 unmodified lines
827 867
828static ssize_t fanotify_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)868static ssize_t fanotify_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
829{869{
830 struct fanotify_response response = { .fd = -1, .response = -1 };870 struct fanotify_response response;
831 struct fsnotify_group *group;871 struct fsnotify_group *group;
832 int ret;872 int ret;
873 const char __user *info_buf = buf + sizeof(struct fanotify_response);
874 size_t info_len;
833 875
834 if (!IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS))876 if (!IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS))
835 return -EINVAL;877 return -EINVAL;
836 878
837 group = file->private_data;879 group = file->private_data;
838 880
881 pr_debug("%s: group=%p count=%zu\n", __func__, group, count);
882
839 if (count < sizeof(response))883 if (count < sizeof(response))
840 return -EINVAL;884 return -EINVAL;
841 885
842 count = sizeof(response);886 if (copy_from_user(&response, buf, sizeof(response)))
843
844 pr_debug("%s: group=%p count=%zu\n", __func__, group, count);
845
846 if (copy_from_user(&response, buf, count))
847 return -EFAULT;887 return -EFAULT;
848 888
849 ret = process_access_response(group, &response);889 info_len = count - sizeof(response);
890
891 ret = process_access_response(group, &response, info_buf, info_len);
850 if (ret < 0)892 if (ret < 0)
851 count = ret;893 count = ret;
894 else
895 count = sizeof(response) + ret;
852 896
853 return count;897 return count;
854}898}
@@ -876,7 +920,7 @@ static int fanotify_release(struct inode *ignored, struct file *file) · 21 unmodified lines
876 event = list_first_entry(&group->fanotify_data.access_list,920 event = list_first_entry(&group->fanotify_data.access_list,
877 struct fanotify_perm_event, fae.fse.list);921 struct fanotify_perm_event, fae.fse.list);
878 list_del_init(&event->fae.fse.list);922 list_del_init(&event->fae.fse.list);
879 finish_permission_event(group, event, FAN_ALLOW);923 finish_permission_event(group, event, FAN_ALLOW, NULL);
880 spin_lock(&group->notification_lock);924 spin_lock(&group->notification_lock);
881 }925 }
882 926
@@ -893,7 +937,7 @@ static int fanotify_release(struct inode *ignored, struct file *file) · 10 unmodified lines
893 fsnotify_destroy_event(group, fsn_event);937 fsnotify_destroy_event(group, fsn_event);
894 } else {938 } else {
895 finish_permission_event(group, FANOTIFY_PERM(event),939 finish_permission_event(group, FANOTIFY_PERM(event),
896 FAN_ALLOW);940 FAN_ALLOW, NULL);
897 }941 }
898 spin_lock(&group->notification_lock);942 spin_lock(&group->notification_lock);
899 }943 }
include/linux/audit.h+5−4
@@ -14,6 +14,7 @@ · 13 unmodified lines
14#include <linux/audit_arch.h>14#include <linux/audit_arch.h>
15#include <uapi/linux/audit.h>15#include <uapi/linux/audit.h>
16#include <uapi/linux/netfilter/nf_tables.h>16#include <uapi/linux/netfilter/nf_tables.h>
17#include <uapi/linux/fanotify.h>
17 18
18#define AUDIT_INO_UNSET ((unsigned long)-1)19#define AUDIT_INO_UNSET ((unsigned long)-1)
19#define AUDIT_DEV_UNSET ((dev_t)-1)20#define AUDIT_DEV_UNSET ((dev_t)-1)
@@ -416,7 +417,7 @@ extern void __audit_log_capset(const struct cred *new, const struct cred *old); · 396 unmodified lines
416extern void __audit_mmap_fd(int fd, int flags);417extern void __audit_mmap_fd(int fd, int flags);
417extern void __audit_openat2_how(struct open_how *how);418extern void __audit_openat2_how(struct open_how *how);
418extern void __audit_log_kern_module(char *name);419extern void __audit_log_kern_module(char *name);
419extern void __audit_fanotify(unsigned int response);420extern void __audit_fanotify(u32 response, struct fanotify_response_info_audit_rule *friar);
420extern void __audit_tk_injoffset(struct timespec64 offset);421extern void __audit_tk_injoffset(struct timespec64 offset);
421extern void __audit_ntp_log(const struct audit_ntp_data *ad);422extern void __audit_ntp_log(const struct audit_ntp_data *ad);
422extern void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,423extern void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
@@ -523,10 +524,10 @@ static inline void audit_log_kern_module(char *name) · 100 unmodified lines
523 __audit_log_kern_module(name);524 __audit_log_kern_module(name);
524}525}
525 526
526static inline void audit_fanotify(unsigned int response)527static inline void audit_fanotify(u32 response, struct fanotify_response_info_audit_rule *friar)
527{528{
528 if (!audit_dummy_context())529 if (!audit_dummy_context())
529 __audit_fanotify(response);530 __audit_fanotify(response, friar);
530}531}
531 532
532static inline void audit_tk_injoffset(struct timespec64 offset)533static inline void audit_tk_injoffset(struct timespec64 offset)
@@ -679,7 +680,7 @@ static inline void audit_log_kern_module(char *name) · 146 unmodified lines
679{680{
680}681}
681 682
682static inline void audit_fanotify(unsigned int response)683static inline void audit_fanotify(u32 response, struct fanotify_response_info_audit_rule *friar)
683{ }684{ }
684 685
685static inline void audit_tk_injoffset(struct timespec64 offset)686static inline void audit_tk_injoffset(struct timespec64 offset)
include/linux/fanotify.h+5−0
@@ -122,6 +122,11 @@ · 121 unmodified lines
122#define ALL_FANOTIFY_EVENT_BITS (FANOTIFY_OUTGOING_EVENTS | \122#define ALL_FANOTIFY_EVENT_BITS (FANOTIFY_OUTGOING_EVENTS | \
123 FANOTIFY_EVENT_FLAGS)123 FANOTIFY_EVENT_FLAGS)
124 124
125/* These masks check for invalid bits in permission responses. */
126#define FANOTIFY_RESPONSE_ACCESS (FAN_ALLOW | FAN_DENY)
127#define FANOTIFY_RESPONSE_FLAGS (FAN_AUDIT | FAN_INFO)
128#define FANOTIFY_RESPONSE_VALID_MASK (FANOTIFY_RESPONSE_ACCESS | FANOTIFY_RESPONSE_FLAGS)
129
125/* Do not use these old uapi constants internally */130/* Do not use these old uapi constants internally */
126#undef FAN_ALL_CLASS_BITS131#undef FAN_ALL_CLASS_BITS
127#undef FAN_ALL_INIT_FLAGS132#undef FAN_ALL_INIT_FLAGS
include/uapi/linux/fanotify.h+29−1
@@ -188,15 +188,43 @@ struct fanotify_event_info_error { · 187 unmodified lines
188 __u32 error_count;188 __u32 error_count;
189};189};
190 190
191/*
192 * User space may need to record additional information about its decision.
193 * The extra information type records what kind of information is included.
194 * The default is none. We also define an extra information buffer whose
195 * size is determined by the extra information type.
196 *
197 * If the information type is Audit Rule, then the information following
198 * is the rule number that triggered the user space decision that
199 * requires auditing.
200 */
201
202#define FAN_RESPONSE_INFO_NONE 0
203#define FAN_RESPONSE_INFO_AUDIT_RULE 1
204
191struct fanotify_response {205struct fanotify_response {
192 __s32 fd;206 __s32 fd;
193 __u32 response;207 __u32 response;
194};208};
195 209
210struct fanotify_response_info_header {
211 __u8 type;
212 __u8 pad;
213 __u16 len;
214};
215
216struct fanotify_response_info_audit_rule {
217 struct fanotify_response_info_header hdr;
218 __u32 rule_number;
219 __u32 subj_trust;
220 __u32 obj_trust;
221};
222
196/* Legit userspace responses to a _PERM event */223/* Legit userspace responses to a _PERM event */
197#define FAN_ALLOW 0x01224#define FAN_ALLOW 0x01
198#define FAN_DENY 0x02225#define FAN_DENY 0x02
199#define FAN_AUDIT 0x10 /* Bit mask to create audit record for result */226#define FAN_AUDIT 0x10 /* Bitmask to create audit record for result */
227#define FAN_INFO 0x20 /* Bitmask to indicate additional information */
200 228
201/* No fd set in event */229/* No fd set in event */
202#define FAN_NOFD -1230#define FAN_NOFD -1
kernel/auditsc.c+15−3
@@ -64,6 +64,7 @@ · 63 unmodified lines
64#include <uapi/linux/limits.h>64#include <uapi/linux/limits.h>
65#include <uapi/linux/netfilter/nf_tables.h>65#include <uapi/linux/netfilter/nf_tables.h>
66#include <uapi/linux/openat2.h> // struct open_how66#include <uapi/linux/openat2.h> // struct open_how
67#include <uapi/linux/fanotify.h>
67 68
68#include "audit.h"69#include "audit.h"
69 70
@@ -2877,10 +2878,21 @@ void __audit_log_kern_module(char *name) · 2807 unmodified lines
2877 context->type = AUDIT_KERN_MODULE;2878 context->type = AUDIT_KERN_MODULE;
2878}2879}
2879 2880
2880void __audit_fanotify(unsigned int response)2881void __audit_fanotify(u32 response, struct fanotify_response_info_audit_rule *friar)
2881{2882{
2882 audit_log(audit_context(), GFP_KERNEL,2883 /* {subj,obj}_trust values are {0,1,2}: no,yes,unknown */
2883 AUDIT_FANOTIFY, "resp=%u", response);2884 switch (friar->hdr.type) {
2885 case FAN_RESPONSE_INFO_NONE:
2886 audit_log(audit_context(), GFP_KERNEL, AUDIT_FANOTIFY,
2887 "resp=%u fan_type=%u fan_info=0 subj_trust=2 obj_trust=2",
2888 response, FAN_RESPONSE_INFO_NONE);
2889 break;
2890 case FAN_RESPONSE_INFO_AUDIT_RULE:
2891 audit_log(audit_context(), GFP_KERNEL, AUDIT_FANOTIFY,
2892 "resp=%u fan_type=%u fan_info=%X subj_trust=%u obj_trust=%u",
2893 response, friar->hdr.type, friar->rule_number,
2894 friar->subj_trust, friar->obj_trust);
2895 }
2884}2896}
2885 2897
2886void __audit_tk_injoffset(struct timespec64 offset)2898void __audit_tk_injoffset(struct timespec64 offset)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t