Skip to content

Commit 72b66e8

Browse files
thestingeranthraxx
authored andcommitted
restrict device timing side channels
Based on the public grsecurity patches.
1 parent 7c0d763 commit 72b66e8

File tree

6 files changed

+55
-5
lines changed

6 files changed

+55
-5
lines changed

fs/stat.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,13 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
4242
stat->gid = inode->i_gid;
4343
stat->rdev = inode->i_rdev;
4444
stat->size = i_size_read(inode);
45-
stat->atime = inode->i_atime;
46-
stat->mtime = inode->i_mtime;
45+
if (is_sidechannel_device(inode) && !capable_noaudit(CAP_MKNOD)) {
46+
stat->atime = inode->i_ctime;
47+
stat->mtime = inode->i_ctime;
48+
} else {
49+
stat->atime = inode->i_atime;
50+
stat->mtime = inode->i_mtime;
51+
}
4752
stat->ctime = inode->i_ctime;
4853
stat->blksize = i_blocksize(inode);
4954
stat->blocks = inode->i_blocks;
@@ -79,9 +84,14 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
7984
if (IS_AUTOMOUNT(inode))
8085
stat->attributes |= STATX_ATTR_AUTOMOUNT;
8186

82-
if (inode->i_op->getattr)
83-
return inode->i_op->getattr(path, stat, request_mask,
84-
query_flags);
87+
if (inode->i_op->getattr) {
88+
int retval = inode->i_op->getattr(path, stat, request_mask, query_flags);
89+
if (!retval && is_sidechannel_device(inode) && !capable_noaudit(CAP_MKNOD)) {
90+
stat->atime = stat->ctime;
91+
stat->mtime = stat->ctime;
92+
}
93+
return retval;
94+
}
8595

8696
generic_fillattr(inode, stat);
8797
return 0;

include/linux/capability.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ extern bool has_capability_noaudit(struct task_struct *t, int cap);
208208
extern bool has_ns_capability_noaudit(struct task_struct *t,
209209
struct user_namespace *ns, int cap);
210210
extern bool capable(int cap);
211+
extern bool capable_noaudit(int cap);
211212
extern bool ns_capable(struct user_namespace *ns, int cap);
212213
extern bool ns_capable_noaudit(struct user_namespace *ns, int cap);
213214
extern bool ns_capable_setid(struct user_namespace *ns, int cap);
@@ -234,6 +235,10 @@ static inline bool capable(int cap)
234235
{
235236
return true;
236237
}
238+
static inline bool capable_noaudit(int cap)
239+
{
240+
return true;
241+
}
237242
static inline bool ns_capable(struct user_namespace *ns, int cap)
238243
{
239244
return true;

include/linux/fs.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3659,4 +3659,15 @@ static inline int inode_drain_writes(struct inode *inode)
36593659
return filemap_write_and_wait(inode->i_mapping);
36603660
}
36613661

3662+
extern int device_sidechannel_restrict;
3663+
3664+
static inline bool is_sidechannel_device(const struct inode *inode)
3665+
{
3666+
umode_t mode;
3667+
if (!device_sidechannel_restrict)
3668+
return false;
3669+
mode = inode->i_mode;
3670+
return ((S_ISCHR(mode) || S_ISBLK(mode)) && (mode & (S_IROTH | S_IWOTH)));
3671+
}
3672+
36623673
#endif /* _LINUX_FS_H */

include/linux/fsnotify.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ static inline void fsnotify_access(struct file *file)
233233
struct inode *inode = file_inode(file);
234234
__u32 mask = FS_ACCESS;
235235

236+
if (is_sidechannel_device(inode))
237+
return;
238+
236239
if (S_ISDIR(inode->i_mode))
237240
mask |= FS_ISDIR;
238241

@@ -249,6 +252,9 @@ static inline void fsnotify_modify(struct file *file)
249252
struct inode *inode = file_inode(file);
250253
__u32 mask = FS_MODIFY;
251254

255+
if (is_sidechannel_device(inode))
256+
return;
257+
252258
if (S_ISDIR(inode->i_mode))
253259
mask |= FS_ISDIR;
254260

kernel/capability.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,12 @@ bool capable(int cap)
449449
return ns_capable(&init_user_ns, cap);
450450
}
451451
EXPORT_SYMBOL(capable);
452+
453+
bool capable_noaudit(int cap)
454+
{
455+
return ns_capable_noaudit(&init_user_ns, cap);
456+
}
457+
EXPORT_SYMBOL(capable_noaudit);
452458
#endif /* CONFIG_MULTIUSER */
453459

454460
/**

kernel/sysctl.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@ static const int cap_last_cap = CAP_LAST_CAP;
160160
static unsigned long hung_task_timeout_max __read_only = (LONG_MAX/HZ);
161161
#endif
162162

163+
int device_sidechannel_restrict __read_mostly = 1;
164+
EXPORT_SYMBOL(device_sidechannel_restrict);
165+
163166
#ifdef CONFIG_INOTIFY_USER
164167
#include <linux/inotify.h>
165168
#endif
@@ -893,6 +896,15 @@ static struct ctl_table kern_table[] = {
893896
.extra2 = &two,
894897
},
895898
#endif
899+
{
900+
.procname = "device_sidechannel_restrict",
901+
.data = &device_sidechannel_restrict,
902+
.maxlen = sizeof(int),
903+
.mode = 0644,
904+
.proc_handler = proc_dointvec_minmax_sysadmin,
905+
.extra1 = SYSCTL_ZERO,
906+
.extra2 = SYSCTL_ONE,
907+
},
896908
{
897909
.procname = "ngroups_max",
898910
.data = &ngroups_max,

0 commit comments

Comments
 (0)