@@ -978,49 +978,68 @@ long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter)
978
978
}
979
979
980
980
#if defined(CONFIG_SECCOMP_FILTER ) && defined(CONFIG_CHECKPOINT_RESTORE )
981
- long seccomp_get_filter (struct task_struct * task , unsigned long filter_off ,
982
- void __user * data )
981
+ static struct seccomp_filter * get_nth_filter (struct task_struct * task ,
982
+ unsigned long filter_off )
983
983
{
984
- struct seccomp_filter * filter ;
985
- struct sock_fprog_kern * fprog ;
986
- long ret ;
987
- unsigned long count = 0 ;
988
-
989
- if (!capable (CAP_SYS_ADMIN ) ||
990
- current -> seccomp .mode != SECCOMP_MODE_DISABLED ) {
991
- return - EACCES ;
992
- }
984
+ struct seccomp_filter * orig , * filter ;
985
+ unsigned long count ;
993
986
987
+ /*
988
+ * Note: this is only correct because the caller should be the (ptrace)
989
+ * tracer of the task, otherwise lock_task_sighand is needed.
990
+ */
994
991
spin_lock_irq (& task -> sighand -> siglock );
992
+
995
993
if (task -> seccomp .mode != SECCOMP_MODE_FILTER ) {
996
- ret = - EINVAL ;
997
- goto out ;
994
+ spin_unlock_irq ( & task -> sighand -> siglock ) ;
995
+ return ERR_PTR ( - EINVAL ) ;
998
996
}
999
997
1000
- filter = task -> seccomp .filter ;
1001
- while (filter ) {
1002
- filter = filter -> prev ;
998
+ orig = task -> seccomp .filter ;
999
+ __get_seccomp_filter (orig );
1000
+ spin_unlock_irq (& task -> sighand -> siglock );
1001
+
1002
+ count = 0 ;
1003
+ for (filter = orig ; filter ; filter = filter -> prev )
1003
1004
count ++ ;
1004
- }
1005
1005
1006
1006
if (filter_off >= count ) {
1007
- ret = - ENOENT ;
1007
+ filter = ERR_PTR ( - ENOENT ) ;
1008
1008
goto out ;
1009
1009
}
1010
- count -= filter_off ;
1011
1010
1012
- filter = task -> seccomp .filter ;
1013
- while (filter && count > 1 ) {
1014
- filter = filter -> prev ;
1011
+ count -= filter_off ;
1012
+ for (filter = orig ; filter && count > 1 ; filter = filter -> prev )
1015
1013
count -- ;
1016
- }
1017
1014
1018
1015
if (WARN_ON (count != 1 || !filter )) {
1019
- /* The filter tree shouldn't shrink while we're using it. */
1020
- ret = - ENOENT ;
1016
+ filter = ERR_PTR (- ENOENT );
1021
1017
goto out ;
1022
1018
}
1023
1019
1020
+ __get_seccomp_filter (filter );
1021
+
1022
+ out :
1023
+ __put_seccomp_filter (orig );
1024
+ return filter ;
1025
+ }
1026
+
1027
+ long seccomp_get_filter (struct task_struct * task , unsigned long filter_off ,
1028
+ void __user * data )
1029
+ {
1030
+ struct seccomp_filter * filter ;
1031
+ struct sock_fprog_kern * fprog ;
1032
+ long ret ;
1033
+
1034
+ if (!capable (CAP_SYS_ADMIN ) ||
1035
+ current -> seccomp .mode != SECCOMP_MODE_DISABLED ) {
1036
+ return - EACCES ;
1037
+ }
1038
+
1039
+ filter = get_nth_filter (task , filter_off );
1040
+ if (IS_ERR (filter ))
1041
+ return PTR_ERR (filter );
1042
+
1024
1043
fprog = filter -> prog -> orig_prog ;
1025
1044
if (!fprog ) {
1026
1045
/* This must be a new non-cBPF filter, since we save
@@ -1035,17 +1054,44 @@ long seccomp_get_filter(struct task_struct *task, unsigned long filter_off,
1035
1054
if (!data )
1036
1055
goto out ;
1037
1056
1038
- __get_seccomp_filter (filter );
1039
- spin_unlock_irq (& task -> sighand -> siglock );
1040
-
1041
1057
if (copy_to_user (data , fprog -> filter , bpf_classic_proglen (fprog )))
1042
1058
ret = - EFAULT ;
1043
1059
1060
+ out :
1044
1061
__put_seccomp_filter (filter );
1045
1062
return ret ;
1063
+ }
1046
1064
1047
- out :
1048
- spin_unlock_irq (& task -> sighand -> siglock );
1065
+ long seccomp_get_metadata (struct task_struct * task ,
1066
+ unsigned long size , void __user * data )
1067
+ {
1068
+ long ret ;
1069
+ struct seccomp_filter * filter ;
1070
+ struct seccomp_metadata kmd = {};
1071
+
1072
+ if (!capable (CAP_SYS_ADMIN ) ||
1073
+ current -> seccomp .mode != SECCOMP_MODE_DISABLED ) {
1074
+ return - EACCES ;
1075
+ }
1076
+
1077
+ size = min_t (unsigned long , size , sizeof (kmd ));
1078
+
1079
+ if (copy_from_user (& kmd , data , size ))
1080
+ return - EFAULT ;
1081
+
1082
+ filter = get_nth_filter (task , kmd .filter_off );
1083
+ if (IS_ERR (filter ))
1084
+ return PTR_ERR (filter );
1085
+
1086
+ memset (& kmd , 0 , sizeof (kmd ));
1087
+ if (filter -> log )
1088
+ kmd .flags |= SECCOMP_FILTER_FLAG_LOG ;
1089
+
1090
+ ret = size ;
1091
+ if (copy_to_user (data , & kmd , size ))
1092
+ ret = - EFAULT ;
1093
+
1094
+ __put_seccomp_filter (filter );
1049
1095
return ret ;
1050
1096
}
1051
1097
#endif
0 commit comments