summaryrefslogtreecommitdiffstats
path: root/debian/patches/features
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 10:06:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 10:06:00 +0000
commitb15a952c52a6825376d3e7f6c1bf5c886c6d8b74 (patch)
tree1500f2f8f276908a36d8126cb632c0d6b1276764 /debian/patches/features
parentAdding upstream version 5.10.209. (diff)
downloadlinux-b15a952c52a6825376d3e7f6c1bf5c886c6d8b74.tar.xz
linux-b15a952c52a6825376d3e7f6c1bf5c886c6d8b74.zip
Adding debian version 5.10.209-2.debian/5.10.209-2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'debian/patches/features')
-rw-r--r--debian/patches/features/all/aufs5/aufs5-base.patch332
-rw-r--r--debian/patches/features/all/aufs5/aufs5-mmap.patch405
-rw-r--r--debian/patches/features/all/aufs5/aufs5-standalone.patch308
-rw-r--r--debian/patches/features/all/db-mok-keyring/0001-MODSIGN-do-not-load-mok-when-secure-boot-disabled.patch40
-rw-r--r--debian/patches/features/all/db-mok-keyring/0003-MODSIGN-checking-the-blacklisted-hash-before-loading-a-kernel-module.patch117
-rw-r--r--debian/patches/features/all/db-mok-keyring/0004-MODSIGN-check-the-attributes-of-db-and-mok.patch113
-rw-r--r--debian/patches/features/all/db-mok-keyring/KEYS-Make-use-of-platform-keyring-for-module-signature.patch37
-rw-r--r--debian/patches/features/all/db-mok-keyring/modsign-make-shash-allocation-failure-fatal.patch28
-rw-r--r--debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch149
-rw-r--r--debian/patches/features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch153
-rw-r--r--debian/patches/features/all/lockdown/efi-add-an-efi_secure_boot-flag-to-indicate-secure-b.patch152
-rw-r--r--debian/patches/features/all/lockdown/efi-lock-down-the-kernel-if-booted-in-secure-boot-mo.patch127
-rw-r--r--debian/patches/features/all/lockdown/mtd-disable-slram-and-phram-when-locked-down.patch75
-rw-r--r--debian/patches/features/all/security-perf-allow-further-restriction-of-perf_event_open.patch80
-rw-r--r--debian/patches/features/arm64/arm64-compat-Implement-misalignment-fixups-for-multi.patch480
-rw-r--r--debian/patches/features/arm64/arm64-dts-raspberry-Add-support-for-the-CM4.patch423
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Add-basic-support-for-Kobol-s-Hel.patch419
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-PCIe-on-helios64.patch113
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-two-PWM-fans-on-h.patch61
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Rely-on-SoC-external-pull-up-on-p.patch32
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-kobol-helios64-Add-mmc-aliases.patch30
-rw-r--r--debian/patches/features/x86/intel-iommu-add-kconfig-option-to-exclude-igpu-by-default.patch85
-rw-r--r--debian/patches/features/x86/intel-iommu-add-option-to-exclude-integrated-gpu-only.patch91
-rw-r--r--debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch193
-rw-r--r--debian/patches/features/x86/x86-memtest-WARN-if-bad-RAM-found.patch28
25 files changed, 4071 insertions, 0 deletions
diff --git a/debian/patches/features/all/aufs5/aufs5-base.patch b/debian/patches/features/all/aufs5/aufs5-base.patch
new file mode 100644
index 000000000..60f24b56b
--- /dev/null
+++ b/debian/patches/features/all/aufs5/aufs5-base.patch
@@ -0,0 +1,332 @@
+From: J. R. Okajima <hooanon05@yahoo.co.jp>
+Date: Tue Apr 7 22:14:47 2020 +0900
+Subject: aufs5.6 base patch
+Origin: https://github.com/sfjro/aufs5-standalone/tree/7c07d9737e9de058981f020d66ac0d4407a80899
+Bug-Debian: https://bugs.debian.org/541828
+
+Patch headers added by debian/bin/genpatch-aufs
+
+SPDX-License-Identifier: GPL-2.0
+aufs5.6 base patch
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index b4a43a9e7fbc..32f7c8c48001 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -2984,6 +2984,19 @@ F: include/linux/audit.h
+ F: include/uapi/linux/audit.h
+ F: kernel/audit*
+
++AUFS (advanced multi layered unification filesystem) FILESYSTEM
++M: "J. R. Okajima" <hooanon05g@gmail.com>
++L: aufs-users@lists.sourceforge.net (members only)
++L: linux-unionfs@vger.kernel.org
++W: http://aufs.sourceforge.net
++T: git://github.com/sfjro/aufs4-linux.git
++S: Supported
++F: Documentation/filesystems/aufs/
++F: Documentation/ABI/testing/debugfs-aufs
++F: Documentation/ABI/testing/sysfs-aufs
++F: fs/aufs/
++F: include/uapi/linux/aufs_type.h
++
+ AUXILIARY DISPLAY DRIVERS
+ M: Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>
+ S: Maintained
+diff --git a/drivers/block/loop.c b/drivers/block/loop.c
+index 475e1a738560..8d77e68aa52b 100644
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -763,6 +763,24 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
+ return error;
+ }
+
++/*
++ * for AUFS
++ * no get/put for file.
++ */
++struct file *loop_backing_file(struct super_block *sb)
++{
++ struct file *ret;
++ struct loop_device *l;
++
++ ret = NULL;
++ if (MAJOR(sb->s_dev) == LOOP_MAJOR) {
++ l = sb->s_bdev->bd_disk->private_data;
++ ret = l->lo_backing_file;
++ }
++ return ret;
++}
++EXPORT_SYMBOL_GPL(loop_backing_file);
++
+ /* loop sysfs attributes */
+
+ static ssize_t loop_attr_show(struct device *dev, char *page,
+diff --git a/fs/dcache.c b/fs/dcache.c
+index 361ea7ab30ea..3cd36474f302 100644
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -1285,7 +1285,7 @@ enum d_walk_ret {
+ *
+ * The @enter() callbacks are called with d_lock held.
+ */
+-static void d_walk(struct dentry *parent, void *data,
++void d_walk(struct dentry *parent, void *data,
+ enum d_walk_ret (*enter)(void *, struct dentry *))
+ {
+ struct dentry *this_parent;
+diff --git a/fs/fcntl.c b/fs/fcntl.c
+index 2e4c0fa2074b..0b28a37f7e50 100644
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -32,7 +32,7 @@
+
+ #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
+
+-static int setfl(int fd, struct file * filp, unsigned long arg)
++int setfl(int fd, struct file *filp, unsigned long arg)
+ {
+ struct inode * inode = file_inode(filp);
+ int error = 0;
+@@ -63,6 +63,8 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
+
+ if (filp->f_op->check_flags)
+ error = filp->f_op->check_flags(arg);
++ if (!error && filp->f_op->setfl)
++ error = filp->f_op->setfl(filp, arg);
+ if (error)
+ return error;
+
+diff --git a/fs/inode.c b/fs/inode.c
+index 72c4c347afb7..a7ff2099c2ef 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -1768,7 +1768,7 @@ EXPORT_SYMBOL(generic_update_time);
+ * This does the actual work of updating an inodes time or version. Must have
+ * had called mnt_want_write() before calling this.
+ */
+-static int update_time(struct inode *inode, struct timespec64 *time, int flags)
++int update_time(struct inode *inode, struct timespec64 *time, int flags)
+ {
+ if (inode->i_op->update_time)
+ return inode->i_op->update_time(inode, time, flags);
+diff --git a/fs/namespace.c b/fs/namespace.c
+index f30ed401cc6d..8ddebaf7ad57 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -792,6 +792,12 @@ static inline int check_mnt(struct mount *mnt)
+ return mnt->mnt_ns == current->nsproxy->mnt_ns;
+ }
+
++/* for aufs, CONFIG_AUFS_BR_FUSE */
++int is_current_mnt_ns(struct vfsmount *mnt)
++{
++ return check_mnt(real_mount(mnt));
++}
++
+ /*
+ * vfsmount lock must be held for write
+ */
+diff --git a/fs/read_write.c b/fs/read_write.c
+index 4fb797822567..744831cd0094 100644
+--- a/fs/read_write.c
++++ b/fs/read_write.c
+@@ -507,6 +507,28 @@ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t
+ return ret;
+ }
+
++vfs_readf_t vfs_readf(struct file *file)
++{
++ const struct file_operations *fop = file->f_op;
++
++ if (fop->read)
++ return fop->read;
++ if (fop->read_iter)
++ return new_sync_read;
++ return ERR_PTR(-ENOSYS); /* doesn't have ->read(|_iter)() op */
++}
++
++vfs_writef_t vfs_writef(struct file *file)
++{
++ const struct file_operations *fop = file->f_op;
++
++ if (fop->write)
++ return fop->write;
++ if (fop->write_iter)
++ return new_sync_write;
++ return ERR_PTR(-ENOSYS); /* doesn't have ->write(|_iter)() op */
++}
++
+ /* caller is responsible for file_start_write/file_end_write */
+ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
+ {
+diff --git a/fs/splice.c b/fs/splice.c
+index d7c8a7c4db07..f0b625e27554 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -839,8 +839,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
+ /*
+ * Attempt to initiate a splice from pipe to file.
+ */
+-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+- loff_t *ppos, size_t len, unsigned int flags)
++long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags)
+ {
+ if (out->f_op->splice_write)
+ return out->f_op->splice_write(pipe, out, ppos, len, flags);
+@@ -850,9 +850,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+ /*
+ * Attempt to initiate a splice from a file to a pipe.
+ */
+-static long do_splice_to(struct file *in, loff_t *ppos,
+- struct pipe_inode_info *pipe, size_t len,
+- unsigned int flags)
++long do_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags)
+ {
+ int ret;
+
+diff --git a/fs/sync.c b/fs/sync.c
+index 1373a610dc78..b7b5a0a0df6f 100644
+--- a/fs/sync.c
++++ b/fs/sync.c
+@@ -28,7 +28,7 @@
+ * wait == 1 case since in that case write_inode() functions do
+ * sync_dirty_buffer() and thus effectively write one block at a time.
+ */
+-static int __sync_filesystem(struct super_block *sb, int wait)
++int __sync_filesystem(struct super_block *sb, int wait)
+ {
+ if (wait)
+ sync_inodes_sb(sb);
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index f5abba86107d..0b008da5678d 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1360,6 +1360,7 @@ extern void fasync_free(struct fasync_struct *);
+ /* can be called from interrupts */
+ extern void kill_fasync(struct fasync_struct **, int, int);
+
++extern int setfl(int fd, struct file *filp, unsigned long arg);
+ extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force);
+ extern int f_setown(struct file *filp, unsigned long arg, int force);
+ extern void f_delown(struct file *filp);
+@@ -1848,6 +1849,7 @@ struct file_operations {
+ ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
+ unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
+ int (*check_flags)(int);
++ int (*setfl)(struct file *, unsigned long);
+ int (*flock) (struct file *, int, struct file_lock *);
+ ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
+ ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
+@@ -1918,6 +1920,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
+ struct iovec *fast_pointer,
+ struct iovec **ret_pointer);
+
++typedef ssize_t (*vfs_readf_t)(struct file *, char __user *, size_t, loff_t *);
++typedef ssize_t (*vfs_writef_t)(struct file *, const char __user *, size_t,
++ loff_t *);
++vfs_readf_t vfs_readf(struct file *file);
++vfs_writef_t vfs_writef(struct file *file);
++
+ extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
+ extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
+ extern ssize_t vfs_readv(struct file *, const struct iovec __user *,
+@@ -2352,6 +2360,7 @@ extern int current_umask(void);
+ extern void ihold(struct inode * inode);
+ extern void iput(struct inode *);
+ extern int generic_update_time(struct inode *, struct timespec64 *, int);
++extern int update_time(struct inode *, struct timespec64 *, int);
+
+ /* /sys/fs */
+ extern struct kobject *fs_kobj;
+@@ -2633,6 +2642,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb)
+ return false;
+ }
+ #endif
++extern int __sync_filesystem(struct super_block *, int);
+ extern int sync_filesystem(struct super_block *);
+ extern const struct file_operations def_blk_fops;
+ extern const struct file_operations def_chr_fops;
+diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
+index 8fce5c98a4b0..c1a3f172e97a 100644
+--- a/include/linux/lockdep.h
++++ b/include/linux/lockdep.h
+@@ -395,6 +395,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock,
+ return lock->key == key;
+ }
+
++struct lock_class *lockdep_hlock_class(struct held_lock *hlock);
++
+ /*
+ * Acquire a lock.
+ *
+@@ -540,6 +542,7 @@ struct lockdep_map { };
+
+ #define lockdep_depth(tsk) (0)
+
++#define lockdep_is_held(lock) (1)
+ #define lockdep_is_held_type(l, r) (1)
+
+ #define lockdep_assert_held(l) do { (void)(l); } while (0)
+diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
+index 8f882f5881e8..6b9808f09843 100644
+--- a/include/linux/mnt_namespace.h
++++ b/include/linux/mnt_namespace.h
+@@ -7,12 +7,15 @@ struct mnt_namespace;
+ struct fs_struct;
+ struct user_namespace;
+ struct ns_common;
++struct vfsmount;
+
+ extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
+ struct user_namespace *, struct fs_struct *);
+ extern void put_mnt_ns(struct mnt_namespace *ns);
+ extern struct ns_common *from_mnt_ns(struct mnt_namespace *);
+
++extern int is_current_mnt_ns(struct vfsmount *mnt);
++
+ extern const struct file_operations proc_mounts_operations;
+ extern const struct file_operations proc_mountinfo_operations;
+ extern const struct file_operations proc_mountstats_operations;
+diff --git a/include/linux/splice.h b/include/linux/splice.h
+index 5c47013f708e..fef6c59ed92a 100644
+--- a/include/linux/splice.h
++++ b/include/linux/splice.h
+@@ -93,4 +93,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *);
+
+ extern const struct pipe_buf_operations page_cache_pipe_buf_ops;
+ extern const struct pipe_buf_operations default_pipe_buf_ops;
++
++extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags);
++extern long do_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags);
+ #endif
+diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
+index 29a8de4c50b9..6cfff5e18c84 100644
+--- a/kernel/locking/lockdep.c
++++ b/kernel/locking/lockdep.c
+@@ -169,7 +169,7 @@ static
+ struct lock_class lock_classes[MAX_LOCKDEP_KEYS];
+ static DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS);
+
+-static inline struct lock_class *hlock_class(struct held_lock *hlock)
++inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
+ {
+ unsigned int class_idx = hlock->class_idx;
+
+@@ -190,6 +190,7 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock)
+ */
+ return lock_classes + class_idx;
+ }
++#define hlock_class(hlock) lockdep_hlock_class(hlock)
+
+ #ifdef CONFIG_LOCK_STAT
+ static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats);
+--
+2.27.0
+
diff --git a/debian/patches/features/all/aufs5/aufs5-mmap.patch b/debian/patches/features/all/aufs5/aufs5-mmap.patch
new file mode 100644
index 000000000..4cf1e0b2b
--- /dev/null
+++ b/debian/patches/features/all/aufs5/aufs5-mmap.patch
@@ -0,0 +1,405 @@
+From: J. R. Okajima <hooanon05@yahoo.co.jp>
+Date: Tue Apr 7 22:14:47 2020 +0900
+Subject: aufs5.6 mmap patch
+Origin: https://github.com/sfjro/aufs5-standalone/tree/7c07d9737e9de058981f020d66ac0d4407a80899
+Bug-Debian: https://bugs.debian.org/541828
+
+Patch headers added by debian/bin/genpatch-aufs
+
+SPDX-License-Identifier: GPL-2.0
+aufs5.6 mmap patch
+
+Index: debian-kernel/fs/proc/base.c
+===================================================================
+--- debian-kernel.orig/fs/proc/base.c
++++ debian-kernel/fs/proc/base.c
+@@ -2170,7 +2170,7 @@ static int map_files_get_link(struct den
+ rc = -ENOENT;
+ vma = find_exact_vma(mm, vm_start, vm_end);
+ if (vma && vma->vm_file) {
+- *path = vma->vm_file->f_path;
++ *path = vma_pr_or_file(vma)->f_path;
+ path_get(path);
+ rc = 0;
+ }
+Index: debian-kernel/fs/proc/nommu.c
+===================================================================
+--- debian-kernel.orig/fs/proc/nommu.c
++++ debian-kernel/fs/proc/nommu.c
+@@ -40,7 +40,10 @@ static int nommu_region_show(struct seq_
+ file = region->vm_file;
+
+ if (file) {
+- struct inode *inode = file_inode(region->vm_file);
++ struct inode *inode;
++
++ file = vmr_pr_or_file(region);
++ inode = file_inode(file);
+ dev = inode->i_sb->s_dev;
+ ino = inode->i_ino;
+ }
+Index: debian-kernel/fs/proc/task_mmu.c
+===================================================================
+--- debian-kernel.orig/fs/proc/task_mmu.c
++++ debian-kernel/fs/proc/task_mmu.c
+@@ -280,7 +280,10 @@ show_map_vma(struct seq_file *m, struct
+ const char *name = NULL;
+
+ if (file) {
+- struct inode *inode = file_inode(vma->vm_file);
++ struct inode *inode;
++
++ file = vma_pr_or_file(vma);
++ inode = file_inode(file);
+ dev = inode->i_sb->s_dev;
+ ino = inode->i_ino;
+ pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
+@@ -1793,7 +1796,7 @@ static int show_numa_map(struct seq_file
+ struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
+ struct vm_area_struct *vma = v;
+ struct numa_maps *md = &numa_priv->md;
+- struct file *file = vma->vm_file;
++ struct file *file = vma_pr_or_file(vma);
+ struct mm_struct *mm = vma->vm_mm;
+ struct mempolicy *pol;
+ char buffer[64];
+Index: debian-kernel/fs/proc/task_nommu.c
+===================================================================
+--- debian-kernel.orig/fs/proc/task_nommu.c
++++ debian-kernel/fs/proc/task_nommu.c
+@@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_fil
+ file = vma->vm_file;
+
+ if (file) {
+- struct inode *inode = file_inode(vma->vm_file);
++ struct inode *inode;
++
++ file = vma_pr_or_file(vma);
++ inode = file_inode(file);
+ dev = inode->i_sb->s_dev;
+ ino = inode->i_ino;
+ pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
+Index: debian-kernel/include/linux/mm.h
+===================================================================
+--- debian-kernel.orig/include/linux/mm.h
++++ debian-kernel/include/linux/mm.h
+@@ -1684,6 +1684,28 @@ static inline void unmap_shared_mapping_
+ unmap_mapping_range(mapping, holebegin, holelen, 0);
+ }
+
++extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int);
++extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[],
++ int);
++extern void vma_do_get_file(struct vm_area_struct *, const char[], int);
++extern void vma_do_fput(struct vm_area_struct *, const char[], int);
++
++#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \
++ __LINE__)
++#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \
++ __LINE__)
++#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__)
++#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__)
++
++#ifndef CONFIG_MMU
++extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int);
++extern void vmr_do_fput(struct vm_region *, const char[], int);
++
++#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \
++ __LINE__)
++#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__)
++#endif /* !CONFIG_MMU */
++
+ extern int access_process_vm(struct task_struct *tsk, unsigned long addr,
+ void *buf, int len, unsigned int gup_flags);
+ extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
+Index: debian-kernel/include/linux/mm_types.h
+===================================================================
+--- debian-kernel.orig/include/linux/mm_types.h
++++ debian-kernel/include/linux/mm_types.h
+@@ -276,6 +276,7 @@ struct vm_region {
+ unsigned long vm_top; /* region allocated to here */
+ unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */
+ struct file *vm_file; /* the backing file or NULL */
++ struct file *vm_prfile; /* the virtual backing file or NULL */
+
+ int vm_usage; /* region usage count (access under nommu_region_sem) */
+ bool vm_icache_flushed : 1; /* true if the icache has been flushed for
+@@ -355,6 +356,7 @@ struct vm_area_struct {
+ unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
+ units */
+ struct file * vm_file; /* File we map to (can be NULL). */
++ struct file *vm_prfile; /* shadow of vm_file */
+ void * vm_private_data; /* was vm_pte (shared mem) */
+
+ #ifdef CONFIG_SWAP
+Index: debian-kernel/kernel/fork.c
+===================================================================
+--- debian-kernel.orig/kernel/fork.c
++++ debian-kernel/kernel/fork.c
+@@ -570,7 +570,7 @@ static __latent_entropy int dup_mmap(str
+ struct inode *inode = file_inode(file);
+ struct address_space *mapping = file->f_mapping;
+
+- get_file(file);
++ vma_get_file(tmp);
+ if (tmp->vm_flags & VM_DENYWRITE)
+ atomic_dec(&inode->i_writecount);
+ i_mmap_lock_write(mapping);
+Index: debian-kernel/mm/Makefile
+===================================================================
+--- debian-kernel.orig/mm/Makefile
++++ debian-kernel/mm/Makefile
+@@ -52,7 +52,7 @@ obj-y := filemap.o mempool.o oom_kill.
+ mm_init.o percpu.o slab_common.o \
+ compaction.o vmacache.o \
+ interval_tree.o list_lru.o workingset.o \
+- debug.o gup.o $(mmu-y)
++ prfile.o debug.o gup.o $(mmu-y)
+
+ # Give 'page_alloc' its own module-parameter namespace
+ page-alloc-y := page_alloc.o
+Index: debian-kernel/mm/filemap.c
+===================================================================
+--- debian-kernel.orig/mm/filemap.c
++++ debian-kernel/mm/filemap.c
+@@ -2676,7 +2676,7 @@ vm_fault_t filemap_page_mkwrite(struct v
+ vm_fault_t ret = VM_FAULT_LOCKED;
+
+ sb_start_pagefault(inode->i_sb);
+- file_update_time(vmf->vma->vm_file);
++ vma_file_update_time(vmf->vma);
+ lock_page(page);
+ if (page->mapping != inode->i_mapping) {
+ unlock_page(page);
+Index: debian-kernel/mm/mmap.c
+===================================================================
+--- debian-kernel.orig/mm/mmap.c
++++ debian-kernel/mm/mmap.c
+@@ -179,7 +179,7 @@ static struct vm_area_struct *remove_vma
+ if (vma->vm_ops && vma->vm_ops->close)
+ vma->vm_ops->close(vma);
+ if (vma->vm_file)
+- fput(vma->vm_file);
++ vma_fput(vma);
+ mpol_put(vma_policy(vma));
+ vm_area_free(vma);
+ return next;
+@@ -910,7 +910,7 @@ again:
+ if (remove_next) {
+ if (file) {
+ uprobe_munmap(next, next->vm_start, next->vm_end);
+- fput(file);
++ vma_fput(vma);
+ }
+ if (next->anon_vma)
+ anon_vma_merge(vma, next);
+@@ -1831,8 +1831,8 @@ out:
+ return addr;
+
+ unmap_and_free_vma:
++ vma_fput(vma);
+ vma->vm_file = NULL;
+- fput(file);
+
+ /* Undo any partial mapping done by a device driver. */
+ unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);
+@@ -2683,7 +2683,7 @@ int __split_vma(struct mm_struct *mm, st
+ goto out_free_mpol;
+
+ if (new->vm_file)
+- get_file(new->vm_file);
++ vma_get_file(new);
+
+ if (new->vm_ops && new->vm_ops->open)
+ new->vm_ops->open(new);
+@@ -2702,7 +2702,7 @@ int __split_vma(struct mm_struct *mm, st
+ if (new->vm_ops && new->vm_ops->close)
+ new->vm_ops->close(new);
+ if (new->vm_file)
+- fput(new->vm_file);
++ vma_fput(new);
+ unlink_anon_vmas(new);
+ out_free_mpol:
+ mpol_put(vma_policy(new));
+@@ -2894,7 +2894,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsign
+ struct vm_area_struct *vma;
+ unsigned long populate = 0;
+ unsigned long ret = -EINVAL;
+- struct file *file;
++ struct file *file, *prfile;
+
+ pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n",
+ current->comm, current->pid);
+@@ -2969,10 +2969,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsign
+ }
+ }
+
+- file = get_file(vma->vm_file);
++ vma_get_file(vma);
++ file = vma->vm_file;
++ prfile = vma->vm_prfile;
+ ret = do_mmap_pgoff(vma->vm_file, start, size,
+ prot, flags, pgoff, &populate, NULL);
++ if (!IS_ERR_VALUE(ret) && file && prfile) {
++ struct vm_area_struct *new_vma;
++
++ new_vma = find_vma(mm, ret);
++ if (!new_vma->vm_prfile)
++ new_vma->vm_prfile = prfile;
++ if (new_vma != vma)
++ get_file(prfile);
++ }
++ /*
++ * two fput()s instead of vma_fput(vma),
++ * coz vma may not be available anymore.
++ */
+ fput(file);
++ if (prfile)
++ fput(prfile);
+ out:
+ mmap_write_unlock(mm);
+ if (populate)
+@@ -3263,7 +3280,7 @@ struct vm_area_struct *copy_vma(struct v
+ if (anon_vma_clone(new_vma, vma))
+ goto out_free_mempol;
+ if (new_vma->vm_file)
+- get_file(new_vma->vm_file);
++ vma_get_file(new_vma);
+ if (new_vma->vm_ops && new_vma->vm_ops->open)
+ new_vma->vm_ops->open(new_vma);
+ vma_link(mm, new_vma, prev, rb_link, rb_parent);
+Index: debian-kernel/mm/nommu.c
+===================================================================
+--- debian-kernel.orig/mm/nommu.c
++++ debian-kernel/mm/nommu.c
+@@ -540,7 +540,7 @@ static void __put_nommu_region(struct vm
+ up_write(&nommu_region_sem);
+
+ if (region->vm_file)
+- fput(region->vm_file);
++ vmr_fput(region);
+
+ /* IO memory and memory shared directly out of the pagecache
+ * from ramfs/tmpfs mustn't be released here */
+@@ -672,7 +672,7 @@ static void delete_vma(struct mm_struct
+ if (vma->vm_ops && vma->vm_ops->close)
+ vma->vm_ops->close(vma);
+ if (vma->vm_file)
+- fput(vma->vm_file);
++ vma_fput(vma);
+ put_nommu_region(vma->vm_region);
+ vm_area_free(vma);
+ }
+@@ -1195,7 +1195,7 @@ unsigned long do_mmap(struct file *file,
+ goto error_just_free;
+ }
+ }
+- fput(region->vm_file);
++ vmr_fput(region);
+ kmem_cache_free(vm_region_jar, region);
+ region = pregion;
+ result = start;
+@@ -1272,10 +1272,10 @@ error_just_free:
+ up_write(&nommu_region_sem);
+ error:
+ if (region->vm_file)
+- fput(region->vm_file);
++ vmr_fput(region);
+ kmem_cache_free(vm_region_jar, region);
+ if (vma->vm_file)
+- fput(vma->vm_file);
++ vma_fput(vma);
+ vm_area_free(vma);
+ return ret;
+
+Index: debian-kernel/mm/prfile.c
+===================================================================
+--- /dev/null
++++ debian-kernel/mm/prfile.c
+@@ -0,0 +1,86 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Mainly for aufs which mmap(2) different file and wants to print different
++ * path in /proc/PID/maps.
++ * Call these functions via macros defined in linux/mm.h.
++ *
++ * See Documentation/filesystems/aufs/design/06mmap.txt
++ *
++ * Copyright (c) 2014-2020 Junjro R. Okajima
++ * Copyright (c) 2014 Ian Campbell
++ */
++
++#include <linux/mm.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++
++/* #define PRFILE_TRACE */
++static inline void prfile_trace(struct file *f, struct file *pr,
++ const char func[], int line, const char func2[])
++{
++#ifdef PRFILE_TRACE
++ if (pr)
++ pr_info("%s:%d: %s, %pD2\n", func, line, func2, f);
++#endif
++}
++
++void vma_do_file_update_time(struct vm_area_struct *vma, const char func[],
++ int line)
++{
++ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
++
++ prfile_trace(f, pr, func, line, __func__);
++ file_update_time(f);
++ if (f && pr)
++ file_update_time(pr);
++}
++
++struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[],
++ int line)
++{
++ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
++
++ prfile_trace(f, pr, func, line, __func__);
++ return (f && pr) ? pr : f;
++}
++
++void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line)
++{
++ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
++
++ prfile_trace(f, pr, func, line, __func__);
++ get_file(f);
++ if (f && pr)
++ get_file(pr);
++}
++
++void vma_do_fput(struct vm_area_struct *vma, const char func[], int line)
++{
++ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
++
++ prfile_trace(f, pr, func, line, __func__);
++ fput(f);
++ if (f && pr)
++ fput(pr);
++}
++
++#ifndef CONFIG_MMU
++struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[],
++ int line)
++{
++ struct file *f = region->vm_file, *pr = region->vm_prfile;
++
++ prfile_trace(f, pr, func, line, __func__);
++ return (f && pr) ? pr : f;
++}
++
++void vmr_do_fput(struct vm_region *region, const char func[], int line)
++{
++ struct file *f = region->vm_file, *pr = region->vm_prfile;
++
++ prfile_trace(f, pr, func, line, __func__);
++ fput(f);
++ if (f && pr)
++ fput(pr);
++}
++#endif /* !CONFIG_MMU */
diff --git a/debian/patches/features/all/aufs5/aufs5-standalone.patch b/debian/patches/features/all/aufs5/aufs5-standalone.patch
new file mode 100644
index 000000000..ffd06c8ce
--- /dev/null
+++ b/debian/patches/features/all/aufs5/aufs5-standalone.patch
@@ -0,0 +1,308 @@
+From: J. R. Okajima <hooanon05@yahoo.co.jp>
+Date: Tue Apr 7 22:14:47 2020 +0900
+Subject: aufs5.6 standalone patch
+Origin: https://github.com/sfjro/aufs5-standalone/tree/7c07d9737e9de058981f020d66ac0d4407a80899
+Bug-Debian: https://bugs.debian.org/541828
+
+Patch headers added by debian/bin/genpatch-aufs
+
+SPDX-License-Identifier: GPL-2.0
+aufs5.6 standalone patch
+
+Index: debian-kernel/fs/dcache.c
+===================================================================
+--- debian-kernel.orig/fs/dcache.c
++++ debian-kernel/fs/dcache.c
+@@ -1390,6 +1390,7 @@ rename_retry:
+ seq = 1;
+ goto again;
+ }
++EXPORT_SYMBOL_GPL(d_walk);
+
+ struct check_mount {
+ struct vfsmount *mnt;
+@@ -2935,6 +2936,7 @@ void d_exchange(struct dentry *dentry1,
+
+ write_sequnlock(&rename_lock);
+ }
++EXPORT_SYMBOL_GPL(d_exchange);
+
+ /**
+ * d_ancestor - search for an ancestor
+Index: debian-kernel/fs/exec.c
+===================================================================
+--- debian-kernel.orig/fs/exec.c
++++ debian-kernel/fs/exec.c
+@@ -111,6 +111,7 @@ bool path_noexec(const struct path *path
+ return (path->mnt->mnt_flags & MNT_NOEXEC) ||
+ (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
+ }
++EXPORT_SYMBOL_GPL(path_noexec);
+
+ #ifdef CONFIG_USELIB
+ /*
+Index: debian-kernel/fs/fcntl.c
+===================================================================
+--- debian-kernel.orig/fs/fcntl.c
++++ debian-kernel/fs/fcntl.c
+@@ -85,6 +85,7 @@ int setfl(int fd, struct file *filp, uns
+ out:
+ return error;
+ }
++EXPORT_SYMBOL_GPL(setfl);
+
+ static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
+ int force)
+Index: debian-kernel/fs/file_table.c
+===================================================================
+--- debian-kernel.orig/fs/file_table.c
++++ debian-kernel/fs/file_table.c
+@@ -162,6 +162,7 @@ over:
+ }
+ return ERR_PTR(-ENFILE);
+ }
++EXPORT_SYMBOL_GPL(alloc_empty_file);
+
+ /*
+ * Variant of alloc_empty_file() that doesn't check and modify nr_files.
+@@ -376,6 +377,7 @@ void __fput_sync(struct file *file)
+ }
+
+ EXPORT_SYMBOL(fput);
++EXPORT_SYMBOL_GPL(__fput_sync);
+
+ void __init files_init(void)
+ {
+Index: debian-kernel/fs/inode.c
+===================================================================
+--- debian-kernel.orig/fs/inode.c
++++ debian-kernel/fs/inode.c
+@@ -1774,6 +1774,7 @@ int update_time(struct inode *inode, str
+ return inode->i_op->update_time(inode, time, flags);
+ return generic_update_time(inode, time, flags);
+ }
++EXPORT_SYMBOL_GPL(update_time);
+
+ /**
+ * touch_atime - update the access time
+Index: debian-kernel/fs/namespace.c
+===================================================================
+--- debian-kernel.orig/fs/namespace.c
++++ debian-kernel/fs/namespace.c
+@@ -431,6 +431,7 @@ void __mnt_drop_write(struct vfsmount *m
+ mnt_dec_writers(real_mount(mnt));
+ preempt_enable();
+ }
++EXPORT_SYMBOL_GPL(__mnt_drop_write);
+
+ /**
+ * mnt_drop_write - give up write access to a mount
+@@ -797,6 +798,7 @@ int is_current_mnt_ns(struct vfsmount *m
+ {
+ return check_mnt(real_mount(mnt));
+ }
++EXPORT_SYMBOL_GPL(is_current_mnt_ns);
+
+ /*
+ * vfsmount lock must be held for write
+@@ -1961,6 +1963,7 @@ int iterate_mounts(int (*f)(struct vfsmo
+ }
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(iterate_mounts);
+
+ static void lock_mnt_tree(struct mount *mnt)
+ {
+Index: debian-kernel/fs/notify/group.c
+===================================================================
+--- debian-kernel.orig/fs/notify/group.c
++++ debian-kernel/fs/notify/group.c
+@@ -100,6 +100,7 @@ void fsnotify_get_group(struct fsnotify_
+ {
+ refcount_inc(&group->refcnt);
+ }
++EXPORT_SYMBOL_GPL(fsnotify_get_group);
+
+ /*
+ * Drop a reference to a group. Free it if it's through.
+Index: debian-kernel/fs/open.c
+===================================================================
+--- debian-kernel.orig/fs/open.c
++++ debian-kernel/fs/open.c
+@@ -65,6 +65,7 @@ int do_truncate(struct dentry *dentry, l
+ inode_unlock(dentry->d_inode);
+ return ret;
+ }
++EXPORT_SYMBOL_GPL(do_truncate);
+
+ long vfs_truncate(const struct path *path, loff_t length)
+ {
+Index: debian-kernel/fs/read_write.c
+===================================================================
+--- debian-kernel.orig/fs/read_write.c
++++ debian-kernel/fs/read_write.c
+@@ -488,6 +488,7 @@ ssize_t vfs_read(struct file *file, char
+ inc_syscr(current);
+ return ret;
+ }
++EXPORT_SYMBOL_GPL(vfs_read);
+
+ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
+ {
+@@ -517,6 +518,7 @@ vfs_readf_t vfs_readf(struct file *file)
+ return new_sync_read;
+ return ERR_PTR(-ENOSYS); /* doesn't have ->read(|_iter)() op */
+ }
++EXPORT_SYMBOL_GPL(vfs_readf);
+
+ vfs_writef_t vfs_writef(struct file *file)
+ {
+@@ -528,6 +530,7 @@ vfs_writef_t vfs_writef(struct file *fil
+ return new_sync_write;
+ return ERR_PTR(-ENOSYS); /* doesn't have ->write(|_iter)() op */
+ }
++EXPORT_SYMBOL_GPL(vfs_writef);
+
+ /* caller is responsible for file_start_write/file_end_write */
+ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
+@@ -608,6 +611,7 @@ ssize_t vfs_write(struct file *file, con
+ file_end_write(file);
+ return ret;
+ }
++EXPORT_SYMBOL_GPL(vfs_write);
+
+ /* file_ppos returns &file->f_pos or NULL if file is stream */
+ static inline loff_t *file_ppos(struct file *file)
+Index: debian-kernel/fs/splice.c
+===================================================================
+--- debian-kernel.orig/fs/splice.c
++++ debian-kernel/fs/splice.c
+@@ -870,6 +870,7 @@ long do_splice_to(struct file *in, loff_
+ return in->f_op->splice_read(in, ppos, pipe, len, flags);
+ return default_file_splice_read(in, ppos, pipe, len, flags);
+ }
++EXPORT_SYMBOL_GPL(do_splice_from);
+
+ /**
+ * splice_direct_to_actor - splices data directly between two non-pipes
+@@ -1016,6 +1017,7 @@ static int direct_splice_actor(struct pi
+ return do_splice_from(pipe, file, sd->opos, sd->total_len,
+ sd->flags);
+ }
++EXPORT_SYMBOL_GPL(do_splice_to);
+
+ /**
+ * do_splice_direct - splices data directly between two files
+Index: debian-kernel/fs/sync.c
+===================================================================
+--- debian-kernel.orig/fs/sync.c
++++ debian-kernel/fs/sync.c
+@@ -39,6 +39,7 @@ int __sync_filesystem(struct super_block
+ sb->s_op->sync_fs(sb, wait);
+ return __sync_blockdev(sb->s_bdev, wait);
+ }
++EXPORT_SYMBOL_GPL(__sync_filesystem);
+
+ /*
+ * Write out and wait upon all dirty data associated with this
+Index: debian-kernel/fs/xattr.c
+===================================================================
+--- debian-kernel.orig/fs/xattr.c
++++ debian-kernel/fs/xattr.c
+@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry
+ *xattr_value = value;
+ return error;
+ }
++EXPORT_SYMBOL_GPL(vfs_getxattr_alloc);
+
+ ssize_t
+ __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
+Index: debian-kernel/kernel/locking/lockdep.c
+===================================================================
+--- debian-kernel.orig/kernel/locking/lockdep.c
++++ debian-kernel/kernel/locking/lockdep.c
+@@ -190,6 +190,7 @@ inline struct lock_class *lockdep_hlock_
+ */
+ return lock_classes + class_idx;
+ }
++EXPORT_SYMBOL_GPL(lockdep_hlock_class);
+ #define hlock_class(hlock) lockdep_hlock_class(hlock)
+
+ #ifdef CONFIG_LOCK_STAT
+Index: debian-kernel/kernel/task_work.c
+===================================================================
+--- debian-kernel.orig/kernel/task_work.c
++++ debian-kernel/kernel/task_work.c
+@@ -139,3 +139,4 @@ void task_work_run(void)
+ } while (work);
+ }
+ }
++EXPORT_SYMBOL_GPL(task_work_run);
+Index: debian-kernel/security/security.c
+===================================================================
+--- debian-kernel.orig/security/security.c
++++ debian-kernel/security/security.c
+@@ -1096,6 +1096,7 @@ int security_path_rmdir(const struct pat
+ return 0;
+ return call_int_hook(path_rmdir, 0, dir, dentry);
+ }
++EXPORT_SYMBOL_GPL(security_path_rmdir);
+
+ int security_path_unlink(const struct path *dir, struct dentry *dentry)
+ {
+@@ -1112,6 +1113,7 @@ int security_path_symlink(const struct p
+ return 0;
+ return call_int_hook(path_symlink, 0, dir, dentry, old_name);
+ }
++EXPORT_SYMBOL_GPL(security_path_symlink);
+
+ int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
+ struct dentry *new_dentry)
+@@ -1120,6 +1122,7 @@ int security_path_link(struct dentry *ol
+ return 0;
+ return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
+ }
++EXPORT_SYMBOL_GPL(security_path_link);
+
+ int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
+ const struct path *new_dir, struct dentry *new_dentry,
+@@ -1147,6 +1150,7 @@ int security_path_truncate(const struct
+ return 0;
+ return call_int_hook(path_truncate, 0, path);
+ }
++EXPORT_SYMBOL_GPL(security_path_truncate);
+
+ int security_path_chmod(const struct path *path, umode_t mode)
+ {
+@@ -1154,6 +1158,7 @@ int security_path_chmod(const struct pat
+ return 0;
+ return call_int_hook(path_chmod, 0, path, mode);
+ }
++EXPORT_SYMBOL_GPL(security_path_chmod);
+
+ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
+ {
+@@ -1161,6 +1166,7 @@ int security_path_chown(const struct pat
+ return 0;
+ return call_int_hook(path_chown, 0, path, uid, gid);
+ }
++EXPORT_SYMBOL_GPL(security_path_chown);
+
+ int security_path_chroot(const struct path *path)
+ {
+@@ -1261,6 +1267,7 @@ int security_inode_permission(struct ino
+ return 0;
+ return call_int_hook(inode_permission, 0, inode, mask);
+ }
++EXPORT_SYMBOL_GPL(security_inode_permission);
+
+ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
+ {
+@@ -1453,6 +1460,7 @@ int security_file_permission(struct file
+
+ return fsnotify_perm(file, mask);
+ }
++EXPORT_SYMBOL_GPL(security_file_permission);
+
+ int security_file_alloc(struct file *file)
+ {
diff --git a/debian/patches/features/all/db-mok-keyring/0001-MODSIGN-do-not-load-mok-when-secure-boot-disabled.patch b/debian/patches/features/all/db-mok-keyring/0001-MODSIGN-do-not-load-mok-when-secure-boot-disabled.patch
new file mode 100644
index 000000000..5d4ec82f0
--- /dev/null
+++ b/debian/patches/features/all/db-mok-keyring/0001-MODSIGN-do-not-load-mok-when-secure-boot-disabled.patch
@@ -0,0 +1,40 @@
+From: "Lee, Chun-Yi" <joeyli.kernel@gmail.com>
+Date: Tue, 13 Mar 2018 18:37:59 +0800
+Subject: [PATCH 1/5] MODSIGN: do not load mok when secure boot disabled
+Origin: https://lore.kernel.org/patchwork/patch/933173/
+
+The mok can not be trusted when the secure boot is disabled. Which
+means that the kernel embedded certificate is the only trusted key.
+
+Due to db/dbx are authenticated variables, they needs manufacturer's
+KEK for update. So db/dbx are secure when secureboot disabled.
+
+Cc: David Howells <dhowells@redhat.com>
+Cc: Josh Boyer <jwboyer@fedoraproject.org>
+Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
+Signed-off-by: "Lee, Chun-Yi" <jlee@suse.com>
+[Rebased by Luca Boccassi]
+[bwh: Forward-ported to 5.5.9:
+ - get_cert_list() takes a pointer to status and returns the cert list
+ - Adjust filename]
+[Salvatore Bonaccorso: Forward-ported to 5.10: Refresh for changes in
+38a1f03aa240 ("integrity: Move import of MokListRT certs to a separate
+routine"). Refresh in context for change in ebd9c2ae369a ("integrity: Load mokx
+variables into the blacklist keyring")]
+---
+ security/integrity/platform_certs/load_uefi.c | 26 +++++++++++++++-----------
+ 1 file changed, 15 insertions(+), 11 deletions(-)
+
+--- a/security/integrity/platform_certs/load_uefi.c
++++ b/security/integrity/platform_certs/load_uefi.c
+@@ -176,6 +176,10 @@ static int __init load_uefi_certs(void)
+ kfree(dbx);
+ }
+
++ /* the MOK can not be trusted when secure boot is disabled */
++ if (!efi_enabled(EFI_SECURE_BOOT))
++ return 0;
++
+ mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status);
+ if (!mokx) {
+ if (status == EFI_NOT_FOUND)
diff --git a/debian/patches/features/all/db-mok-keyring/0003-MODSIGN-checking-the-blacklisted-hash-before-loading-a-kernel-module.patch b/debian/patches/features/all/db-mok-keyring/0003-MODSIGN-checking-the-blacklisted-hash-before-loading-a-kernel-module.patch
new file mode 100644
index 000000000..a7ec5ccb5
--- /dev/null
+++ b/debian/patches/features/all/db-mok-keyring/0003-MODSIGN-checking-the-blacklisted-hash-before-loading-a-kernel-module.patch
@@ -0,0 +1,117 @@
+From: "Lee, Chun-Yi" <joeyli.kernel@gmail.com>
+Date: Tue, 13 Mar 2018 18:38:02 +0800
+Subject: [PATCH 3/4] MODSIGN: checking the blacklisted hash before loading a
+ kernel module
+Origin: https://lore.kernel.org/patchwork/patch/933175/
+
+This patch adds the logic for checking the kernel module's hash
+base on blacklist. The hash must be generated by sha256 and enrolled
+to dbx/mokx.
+
+For example:
+ sha256sum sample.ko
+ mokutil --mokx --import-hash $HASH_RESULT
+
+Whether the signature on ko file is stripped or not, the hash can be
+compared by kernel.
+
+Cc: David Howells <dhowells@redhat.com>
+Cc: Josh Boyer <jwboyer@fedoraproject.org>
+Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
+Signed-off-by: "Lee, Chun-Yi" <jlee@suse.com>
+[Rebased by Luca Boccassi]
+---
+ kernel/module_signing.c | 59 +++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 57 insertions(+), 2 deletions(-)
+
+--- a/kernel/module_signing.c
++++ b/kernel/module_signing.c
+@@ -12,15 +12,62 @@
+ #include <linux/string.h>
+ #include <linux/verification.h>
+ #include <crypto/public_key.h>
++#include <crypto/hash.h>
++#include <keys/system_keyring.h>
+ #include "module-internal.h"
+
++static int mod_is_hash_blacklisted(const void *mod, size_t verifylen)
++{
++ struct crypto_shash *tfm;
++ struct shash_desc *desc;
++ size_t digest_size, desc_size;
++ u8 *digest;
++ int ret = 0;
++
++ tfm = crypto_alloc_shash("sha256", 0, 0);
++ if (IS_ERR(tfm))
++ goto error_return;
++
++ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
++ digest_size = crypto_shash_digestsize(tfm);
++ digest = kzalloc(digest_size + desc_size, GFP_KERNEL);
++ if (!digest) {
++ pr_err("digest memory buffer allocate fail\n");
++ ret = -ENOMEM;
++ goto error_digest;
++ }
++ desc = (void *)digest + digest_size;
++ desc->tfm = tfm;
++ ret = crypto_shash_init(desc);
++ if (ret < 0)
++ goto error_shash;
++
++ ret = crypto_shash_finup(desc, mod, verifylen, digest);
++ if (ret < 0)
++ goto error_shash;
++
++ pr_debug("%ld digest: %*phN\n", verifylen, (int) digest_size, digest);
++
++ ret = is_hash_blacklisted(digest, digest_size, "bin");
++ if (ret == -EKEYREJECTED)
++ pr_err("Module hash %*phN is blacklisted\n",
++ (int) digest_size, digest);
++
++error_shash:
++ kfree(digest);
++error_digest:
++ crypto_free_shash(tfm);
++error_return:
++ return ret;
++}
++
+ /*
+ * Verify the signature on a module.
+ */
+ int mod_verify_sig(const void *mod, struct load_info *info)
+ {
+ struct module_signature ms;
+- size_t sig_len, modlen = info->len;
++ size_t sig_len, modlen = info->len, wholelen;
+ int ret;
+
+ pr_devel("==>%s(,%zu)\n", __func__, modlen);
+@@ -28,6 +75,7 @@ int mod_verify_sig(const void *mod, stru
+ if (modlen <= sizeof(ms))
+ return -EBADMSG;
+
++ wholelen = modlen + sizeof(MODULE_SIG_STRING) - 1;
+ memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
+
+ ret = mod_check_sig(&ms, modlen, "module");
+@@ -38,8 +86,15 @@ int mod_verify_sig(const void *mod, stru
+ modlen -= sig_len + sizeof(ms);
+ info->len = modlen;
+
+- return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
++ ret = verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
+ VERIFY_USE_SECONDARY_KEYRING,
+ VERIFYING_MODULE_SIGNATURE,
+ NULL, NULL);
++ pr_devel("verify_pkcs7_signature() = %d\n", ret);
++
++ /* checking hash of module is in blacklist */
++ if (!ret)
++ ret = mod_is_hash_blacklisted(mod, wholelen);
++
++ return ret;
+ }
diff --git a/debian/patches/features/all/db-mok-keyring/0004-MODSIGN-check-the-attributes-of-db-and-mok.patch b/debian/patches/features/all/db-mok-keyring/0004-MODSIGN-check-the-attributes-of-db-and-mok.patch
new file mode 100644
index 000000000..530885944
--- /dev/null
+++ b/debian/patches/features/all/db-mok-keyring/0004-MODSIGN-check-the-attributes-of-db-and-mok.patch
@@ -0,0 +1,113 @@
+From: "Lee, Chun-Yi" <joeyli.kernel@gmail.com>
+Date: Tue, 13 Mar 2018 18:38:03 +0800
+Subject: [PATCH 4/4] MODSIGN: check the attributes of db and mok
+Origin: https://lore.kernel.org/patchwork/patch/933176/
+
+That's better for checking the attributes of db and mok variables
+before loading certificates to kernel keyring.
+
+For db and dbx, both of them are authenticated variables. Which
+means that they can only be modified by manufacturer's key. So
+the kernel should checks EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
+attribute before we trust it.
+
+For mok-rt and mokx-rt, both of them are created by shim boot loader
+to forward the mok/mokx content to runtime. They must be runtime-volatile
+variables. So kernel should checks that the attributes map did not set
+EFI_VARIABLE_NON_VOLATILE bit before we trust it.
+
+Cc: David Howells <dhowells@redhat.com>
+Cc: Josh Boyer <jwboyer@fedoraproject.org>
+Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
+Signed-off-by: "Lee, Chun-Yi" <jlee@suse.com>
+[Rebased by Luca Boccassi]
+[bwh: Forward-ported to 5.5.9:
+ - get_cert_list() takes a pointer to status and returns the cert list
+ - Adjust filename, context]
+[bwh: Forward-ported to 5.10: MokListRT and MokListXRT are now both
+ loaded through a single code path.]
+---
+ security/integrity/platform_certs/load_uefi.c | 27 ++++++++++++++-----
+ 1 file changed, 21 insertions(+), 6 deletions(-)
+
+--- a/security/integrity/platform_certs/load_uefi.c
++++ b/security/integrity/platform_certs/load_uefi.c
+@@ -35,11 +35,13 @@ static __init bool uefi_check_ignore_db(
+ * Get a certificate list blob from the named EFI variable.
+ */
+ static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
+- unsigned long *size, efi_status_t *status)
++ unsigned long *size, efi_status_t *status,
++ u32 pos_attr, u32 neg_attr)
+ {
+ unsigned long lsize = 4;
+ unsigned long tmpdb[4];
+ void *db;
++ u32 attr = 0;
+
+ *status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
+ if (*status == EFI_NOT_FOUND)
+@@ -54,13 +56,22 @@ static __init void *get_cert_list(efi_ch
+ if (!db)
+ return NULL;
+
+- *status = efi.get_variable(name, guid, NULL, &lsize, db);
++ *status = efi.get_variable(name, guid, &attr, &lsize, db);
+ if (*status != EFI_SUCCESS) {
+ kfree(db);
+ pr_err("Error reading db var: 0x%lx\n", *status);
+ return NULL;
+ }
+
++ /* must have positive attributes and no negative attributes */
++ if ((pos_attr && !(attr & pos_attr)) ||
++ (neg_attr && (attr & neg_attr))) {
++ kfree(db);
++ pr_err("Error reading db var attributes: 0x%016x\n", attr);
++ *status = EFI_SECURITY_VIOLATION;
++ return NULL;
++ }
++
+ *size = lsize;
+ return db;
+ }
+@@ -106,7 +117,8 @@ static int __init load_moklist_certs(voi
+ /* Get MokListRT. It might not exist, so it isn't an error
+ * if we can't get it.
+ */
+- mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status);
++ mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status,
++ 0, EFI_VARIABLE_NON_VOLATILE);
+ if (mok) {
+ rc = parse_efi_signature_list("UEFI:MokListRT",
+ mok, moksize, get_handler_for_db);
+@@ -145,7 +157,8 @@ static int __init load_uefi_certs(void)
+ * if we can't get them.
+ */
+ if (!uefi_check_ignore_db()) {
+- db = get_cert_list(L"db", &secure_var, &dbsize, &status);
++ db = get_cert_list(L"db", &secure_var, &dbsize, &status,
++ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, 0);
+ if (!db) {
+ if (status == EFI_NOT_FOUND)
+ pr_debug("MODSIGN: db variable wasn't found\n");
+@@ -161,7 +174,8 @@ static int __init load_uefi_certs(void)
+ }
+ }
+
+- dbx = get_cert_list(L"dbx", &secure_var, &dbxsize, &status);
++ dbx = get_cert_list(L"dbx", &secure_var, &dbxsize, &status,
++ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, 0);
+ if (!dbx) {
+ if (status == EFI_NOT_FOUND)
+ pr_debug("dbx variable wasn't found\n");
+@@ -180,7 +194,8 @@ static int __init load_uefi_certs(void)
+ if (!efi_enabled(EFI_SECURE_BOOT))
+ return 0;
+
+- mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status);
++ mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status,
++ 0, EFI_VARIABLE_NON_VOLATILE);
+ if (!mokx) {
+ if (status == EFI_NOT_FOUND)
+ pr_debug("mokx variable wasn't found\n");
diff --git a/debian/patches/features/all/db-mok-keyring/KEYS-Make-use-of-platform-keyring-for-module-signature.patch b/debian/patches/features/all/db-mok-keyring/KEYS-Make-use-of-platform-keyring-for-module-signature.patch
new file mode 100644
index 000000000..f00bf3d24
--- /dev/null
+++ b/debian/patches/features/all/db-mok-keyring/KEYS-Make-use-of-platform-keyring-for-module-signature.patch
@@ -0,0 +1,37 @@
+From: Robert Holmes <robeholmes@gmail.com>
+Date: Tue, 23 Apr 2019 07:39:29 +0000
+Subject: [PATCH] KEYS: Make use of platform keyring for module signature
+ verify
+Bug-Debian: https://bugs.debian.org/935945
+Origin: https://src.fedoraproject.org/rpms/kernel/raw/master/f/KEYS-Make-use-of-platform-keyring-for-module-signature.patch
+
+This patch completes commit 278311e417be ("kexec, KEYS: Make use of
+platform keyring for signature verify") which, while adding the
+platform keyring for bzImage verification, neglected to also add
+this keyring for module verification.
+
+As such, kernel modules signed with keys from the MokList variable
+were not successfully verified.
+
+Signed-off-by: Robert Holmes <robeholmes@gmail.com>
+Signed-off-by: Jeremy Cline <jcline@redhat.com>
+---
+ kernel/module_signing.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+--- a/kernel/module_signing.c
++++ b/kernel/module_signing.c
+@@ -135,6 +135,13 @@ int mod_verify_sig(const void *mod, stru
+ VERIFYING_MODULE_SIGNATURE,
+ NULL, NULL);
+ pr_devel("verify_pkcs7_signature() = %d\n", ret);
++ if (ret == -ENOKEY && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING)) {
++ ret = verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
++ VERIFY_USE_PLATFORM_KEYRING,
++ VERIFYING_MODULE_SIGNATURE,
++ NULL, NULL);
++ pr_devel("verify_pkcs7_signature() = %d\n", ret);
++ }
+
+ /* checking hash of module is in blacklist */
+ if (!ret)
diff --git a/debian/patches/features/all/db-mok-keyring/modsign-make-shash-allocation-failure-fatal.patch b/debian/patches/features/all/db-mok-keyring/modsign-make-shash-allocation-failure-fatal.patch
new file mode 100644
index 000000000..2ae3ddde4
--- /dev/null
+++ b/debian/patches/features/all/db-mok-keyring/modsign-make-shash-allocation-failure-fatal.patch
@@ -0,0 +1,28 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sun, 05 May 2019 13:45:06 +0100
+Subject: MODSIGN: Make shash allocation failure fatal
+
+mod_is_hash_blacklisted() currently returns 0 (suceess) if
+crypto_alloc_shash() fails. This should instead be a fatal error,
+so unwrap and pass up the error code.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/kernel/module_signing.c
++++ b/kernel/module_signing.c
+@@ -51,11 +51,13 @@ static int mod_is_hash_blacklisted(const
+ struct shash_desc *desc;
+ size_t digest_size, desc_size;
+ u8 *digest;
+- int ret = 0;
++ int ret;
+
+ tfm = crypto_alloc_shash("sha256", 0, 0);
+- if (IS_ERR(tfm))
++ if (IS_ERR(tfm)) {
++ ret = PTR_ERR(tfm);
+ goto error_return;
++ }
+
+ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
+ digest_size = crypto_shash_digestsize(tfm);
diff --git a/debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch b/debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch
new file mode 100644
index 000000000..a24ba17ef
--- /dev/null
+++ b/debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch
@@ -0,0 +1,149 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 24 Aug 2009 23:19:58 +0100
+Subject: af9005: Use request_firmware() to load register init script
+Forwarded: no
+
+Read the register init script from the Windows driver. This is sick
+but should avoid the potential copyright infringement in distributing
+a version of the script which is directly derived from the driver.
+---
+ drivers/media/dvb/dvb-usb/Kconfig | 2 +-
+ drivers/media/dvb/dvb-usb/af9005-fe.c | 66 ++++++++++++++++++++++++++------
+ 2 files changed, 54 insertions(+), 14 deletions(-)
+
+Index: debian-kernel/drivers/media/usb/dvb-usb/Kconfig
+===================================================================
+--- debian-kernel.orig/drivers/media/usb/dvb-usb/Kconfig
++++ debian-kernel/drivers/media/usb/dvb-usb/Kconfig
+@@ -260,10 +260,10 @@ config DVB_USB_OPERA1
+
+ config DVB_USB_AF9005
+ tristate "Afatech AF9005 DVB-T USB1.1 support"
+- depends on BROKEN
+ depends on DVB_USB
+ select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
+ select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
++ select FW_LOADER
+ help
+ Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver
+ and the TerraTec Cinergy T USB XE (Rev.1)
+Index: debian-kernel/drivers/media/usb/dvb-usb/af9005-fe.c
+===================================================================
+--- debian-kernel.orig/drivers/media/usb/dvb-usb/af9005-fe.c
++++ debian-kernel/drivers/media/usb/dvb-usb/af9005-fe.c
+@@ -9,10 +9,26 @@
+ * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
+ */
+ #include "af9005.h"
+-#include "af9005-script.h"
+ #include "mt2060.h"
+ #include "qt1010.h"
+ #include <asm/div64.h>
++#include <linux/firmware.h>
++
++/* Register initialisation script to be extracted from the Windows driver */
++
++typedef struct {
++ __le16 reg;
++ u8 pos;
++ u8 len;
++ u8 val;
++ u8 pad;
++} __packed RegDesc;
++
++#define WIN_DRV_NAME "AF05BDA.sys"
++#define WIN_DRV_VERSION "6.3.2.1"
++#define WIN_DRV_SIZE 133504
++#define WIN_DRV_SCRIPT_OFFSET 88316
++#define WIN_DRV_SCRIPT_SIZE 1110
+
+ struct af9005_fe_state {
+ struct dvb_usb_device *d;
+@@ -804,6 +820,8 @@ static int af9005_fe_init(struct dvb_fro
+ {
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
++ const struct firmware *fw;
++ const RegDesc *script;
+ int ret, i, scriptlen;
+ u8 temp, temp0 = 0, temp1 = 0, temp2 = 0;
+ u8 buf[2];
+@@ -956,37 +974,55 @@ static int af9005_fe_init(struct dvb_fro
+ if ((ret = af9005_write_ofdm_register(state->d, 0xaefb, 0x01)))
+ return ret;
+
+- /* load init script */
+- deb_info("load init script\n");
+- scriptlen = sizeof(script) / sizeof(RegDesc);
++ /* load and validate init script */
++ deb_info("load init script from Windows driver\n");
++ ret = request_firmware(&fw, WIN_DRV_NAME, &state->d->udev->dev);
++ if (ret)
++ return ret;
++ BUILD_BUG_ON(sizeof(RegDesc) != 6);
++ if (fw->size != WIN_DRV_SIZE ||
++ memcmp(fw->data + WIN_DRV_SCRIPT_OFFSET,
++ "\x80\xa1\x00\x08\x0a\x00", 6) ||
++ memcmp(fw->data + WIN_DRV_SCRIPT_OFFSET + WIN_DRV_SCRIPT_SIZE - 6,
++ "\x49\xa3\x00\x06\x02\x00", 6)) {
++ err("%s is invalid - should be version %s, size %u bytes\n",
++ WIN_DRV_NAME, WIN_DRV_VERSION, WIN_DRV_SIZE);
++ ret = -EINVAL;
++ goto fail_release;
++ }
++
++ script = (const RegDesc *)(fw->data + WIN_DRV_SCRIPT_OFFSET);
++ scriptlen = WIN_DRV_SCRIPT_SIZE / sizeof(RegDesc);
+ for (i = 0; i < scriptlen; i++) {
++ u16 reg = le16_to_cpu(script[i].reg);
+ if ((ret =
+- af9005_write_register_bits(state->d, script[i].reg,
++ af9005_write_register_bits(state->d, reg,
+ script[i].pos,
+ script[i].len, script[i].val)))
+- return ret;
++ goto fail_release;
+ /* save 3 bytes of original fcw */
+- if (script[i].reg == 0xae18)
++ if (reg == 0xae18)
+ temp2 = script[i].val;
+- if (script[i].reg == 0xae19)
++ if (reg == 0xae19)
+ temp1 = script[i].val;
+- if (script[i].reg == 0xae1a)
++ if (reg == 0xae1a)
+ temp0 = script[i].val;
+
+ /* save original unplug threshold */
+- if (script[i].reg == xd_p_reg_unplug_th)
++ if (reg == xd_p_reg_unplug_th)
+ state->original_if_unplug_th = script[i].val;
+- if (script[i].reg == xd_p_reg_unplug_rf_gain_th)
++ if (reg == xd_p_reg_unplug_rf_gain_th)
+ state->original_rf_unplug_th = script[i].val;
+- if (script[i].reg == xd_p_reg_unplug_dtop_if_gain_th)
++ if (reg == xd_p_reg_unplug_dtop_if_gain_th)
+ state->original_dtop_if_unplug_th = script[i].val;
+- if (script[i].reg == xd_p_reg_unplug_dtop_rf_gain_th)
++ if (reg == xd_p_reg_unplug_dtop_rf_gain_th)
+ state->original_dtop_rf_unplug_th = script[i].val;
+
+ }
+ state->original_fcw =
+ ((u32) temp2 << 16) + ((u32) temp1 << 8) + (u32) temp0;
+
++ release_firmware(fw);
+
+ /* save original TOPs */
+ deb_info("save original TOPs\n");
+@@ -1066,6 +1102,10 @@ static int af9005_fe_init(struct dvb_fro
+
+ deb_info("profit!\n");
+ return 0;
++
++fail_release:
++ release_firmware(fw);
++ return ret;
+ }
+
+ static int af9005_fe_sleep(struct dvb_frontend *fe)
diff --git a/debian/patches/features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch b/debian/patches/features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch
new file mode 100644
index 000000000..7f9ee1cf9
--- /dev/null
+++ b/debian/patches/features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch
@@ -0,0 +1,153 @@
+From: Linn Crosetto <linn@hpe.com>
+Date: Tue, 30 Aug 2016 11:54:38 -0600
+Subject: arm64: add kernel config option to lock down when in Secure Boot mode
+Bug-Debian: https://bugs.debian.org/831827
+Forwarded: no
+
+Add a kernel configuration option to lock down the kernel, to restrict
+userspace's ability to modify the running kernel when UEFI Secure Boot is
+enabled. Based on the x86 patch by Matthew Garrett.
+
+Determine the state of Secure Boot in the EFI stub and pass this to the
+kernel using the FDT.
+
+Signed-off-by: Linn Crosetto <linn@hpe.com>
+[bwh: Forward-ported to 4.10: adjust context]
+[Lukas Wunner: Forward-ported to 4.11: drop parts applied upstream]
+[bwh: Forward-ported to 4.15 and lockdown patch set:
+ - Pass result of efi_get_secureboot() in stub through to
+ efi_set_secure_boot() in main kernel
+ - Use lockdown API and naming]
+[bwh: Forward-ported to 4.19.3: adjust context in update_fdt()]
+[dannf: Moved init_lockdown() call after uefi_init(), fixing SB detection]
+[bwh: Drop call to init_lockdown(), as efi_set_secure_boot() now calls this]
+[bwh: Forward-ported to 5.6: efi_get_secureboot() no longer takes a
+ sys_table parameter]
+[bwh: Forward-ported to 5.7: EFI initialisation from FDT was rewritten, so:
+ - Add Secure Boot mode to the parameter enumeration in fdtparams.c
+ - Add a parameter to efi_get_fdt_params() to return the Secure Boot mode
+ - Since Xen does not have a property name defined for Secure Boot mode,
+ change efi_get_fdt_prop() to handle a missing property name by clearing
+ the output variable]
+[Salvatore Bonaccorso: Forward-ported to 5.10: f30f242fb131 ("efi: Rename
+arm-init to efi-init common for all arch") renamed arm-init.c to efi-init.c]
+---
+ drivers/firmware/efi/efi-init.c | 5 ++++-
+ drivers/firmware/efi/fdtparams.c | 12 +++++++++++-
+ drivers/firmware/efi/libstub/fdt.c | 6 ++++++
+ include/linux/efi.h | 3 ++-
+ 4 files changed, 23 insertions(+), 3 deletions(-)
+
+--- a/drivers/firmware/efi/efi-init.c
++++ b/drivers/firmware/efi/efi-init.c
+@@ -210,9 +210,10 @@ void __init efi_init(void)
+ {
+ struct efi_memory_map_data data;
+ u64 efi_system_table;
++ u32 secure_boot;
+
+ /* Grab UEFI information placed in FDT by stub */
+- efi_system_table = efi_get_fdt_params(&data);
++ efi_system_table = efi_get_fdt_params(&data, &secure_boot);
+ if (!efi_system_table)
+ return;
+
+@@ -234,6 +235,8 @@ void __init efi_init(void)
+ return;
+ }
+
++ efi_set_secure_boot(secure_boot);
++
+ reserve_regions();
+ efi_esrt_init();
+ efi_mokvar_table_init();
+--- a/drivers/firmware/efi/fdtparams.c
++++ b/drivers/firmware/efi/fdtparams.c
+@@ -16,6 +16,7 @@ enum {
+ MMSIZE,
+ DCSIZE,
+ DCVERS,
++ SBMODE,
+
+ PARAMCOUNT
+ };
+@@ -26,6 +27,7 @@ static __initconst const char name[][22]
+ [MMSIZE] = "MemMap Size ",
+ [DCSIZE] = "MemMap Desc. Size ",
+ [DCVERS] = "MemMap Desc. Version ",
++ [SBMODE] = "Secure Boot Enabled ",
+ };
+
+ static __initconst const struct {
+@@ -41,6 +43,7 @@ static __initconst const struct {
+ [MMSIZE] = "xen,uefi-mmap-size",
+ [DCSIZE] = "xen,uefi-mmap-desc-size",
+ [DCVERS] = "xen,uefi-mmap-desc-ver",
++ [SBMODE] = "",
+ }
+ }, {
+ #endif
+@@ -51,6 +54,7 @@ static __initconst const struct {
+ [MMSIZE] = "linux,uefi-mmap-size",
+ [DCSIZE] = "linux,uefi-mmap-desc-size",
+ [DCVERS] = "linux,uefi-mmap-desc-ver",
++ [SBMODE] = "linux,uefi-secure-boot",
+ }
+ }
+ };
+@@ -62,6 +66,11 @@ static int __init efi_get_fdt_prop(const
+ int len;
+ u64 val;
+
++ if (!pname[0]) {
++ memset(var, 0, size);
++ return 0;
++ }
++
+ prop = fdt_getprop(fdt, node, pname, &len);
+ if (!prop)
+ return 1;
+@@ -79,7 +88,7 @@ static int __init efi_get_fdt_prop(const
+ return 0;
+ }
+
+-u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm)
++u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm, u32 *secure_boot)
+ {
+ const void *fdt = initial_boot_params;
+ unsigned long systab;
+@@ -93,6 +102,7 @@ u64 __init efi_get_fdt_params(struct efi
+ [MMSIZE] = { &mm->size, sizeof(mm->size) },
+ [DCSIZE] = { &mm->desc_size, sizeof(mm->desc_size) },
+ [DCVERS] = { &mm->desc_version, sizeof(mm->desc_version) },
++ [SBMODE] = { secure_boot, sizeof(*secure_boot) },
+ };
+
+ BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(name));
+--- a/drivers/firmware/efi/libstub/fdt.c
++++ b/drivers/firmware/efi/libstub/fdt.c
+@@ -148,6 +148,12 @@ static efi_status_t update_fdt(void *ori
+ }
+ }
+
++ fdt_val32 = cpu_to_fdt32(efi_get_secureboot());
++ status = fdt_setprop(fdt, node, "linux,uefi-secure-boot",
++ &fdt_val32, sizeof(fdt_val32));
++ if (status)
++ goto fdt_set_fail;
++
+ /* Shrink the FDT back to its minimum size: */
+ fdt_pack(fdt);
+
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -665,7 +665,8 @@ extern void efi_mem_reserve(phys_addr_t
+ extern int efi_mem_reserve_persistent(phys_addr_t addr, u64 size);
+ extern void efi_initialize_iomem_resources(struct resource *code_resource,
+ struct resource *data_resource, struct resource *bss_resource);
+-extern u64 efi_get_fdt_params(struct efi_memory_map_data *data);
++extern u64 efi_get_fdt_params(struct efi_memory_map_data *data,
++ u32 *secure_boot);
+ extern struct kobject *efi_kobj;
+
+ extern int efi_reboot_quirk_mode;
diff --git a/debian/patches/features/all/lockdown/efi-add-an-efi_secure_boot-flag-to-indicate-secure-b.patch b/debian/patches/features/all/lockdown/efi-add-an-efi_secure_boot-flag-to-indicate-secure-b.patch
new file mode 100644
index 000000000..431281249
--- /dev/null
+++ b/debian/patches/features/all/lockdown/efi-add-an-efi_secure_boot-flag-to-indicate-secure-b.patch
@@ -0,0 +1,152 @@
+From: David Howells <dhowells@redhat.com>
+Date: Mon, 18 Feb 2019 12:45:03 +0000
+Subject: [28/30] efi: Add an EFI_SECURE_BOOT flag to indicate secure boot mode
+Origin: https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/commit?id=a5d70c55c603233c192b375f72116a395909da28
+
+UEFI machines can be booted in Secure Boot mode. Add an EFI_SECURE_BOOT
+flag that can be passed to efi_enabled() to find out whether secure boot is
+enabled.
+
+Move the switch-statement in x86's setup_arch() that inteprets the
+secure_boot boot parameter to generic code and set the bit there.
+
+Suggested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+cc: linux-efi@vger.kernel.org
+[rperier: Forward-ported to 5.5:
+ - Use pr_warn()
+ - Adjust context]
+[bwh: Forward-ported to 5.6: adjust context]
+[bwh: Forward-ported to 5.7:
+ - Use the next available bit in efi.flags
+ - Adjust context]
+---
+ arch/x86/kernel/setup.c | 14 +----------
+ drivers/firmware/efi/Makefile | 1 +
+ drivers/firmware/efi/secureboot.c | 39 +++++++++++++++++++++++++++++++
+ include/linux/efi.h | 16 ++++++++-----
+ 4 files changed, 51 insertions(+), 19 deletions(-)
+ create mode 100644 drivers/firmware/efi/secureboot.c
+
+--- a/arch/x86/kernel/setup.c
++++ b/arch/x86/kernel/setup.c
+@@ -1124,19 +1124,7 @@ void __init setup_arch(char **cmdline_p)
+ /* Allocate bigger log buffer */
+ setup_log_buf(1);
+
+- if (efi_enabled(EFI_BOOT)) {
+- switch (boot_params.secure_boot) {
+- case efi_secureboot_mode_disabled:
+- pr_info("Secure boot disabled\n");
+- break;
+- case efi_secureboot_mode_enabled:
+- pr_info("Secure boot enabled\n");
+- break;
+- default:
+- pr_info("Secure boot could not be determined\n");
+- break;
+- }
+- }
++ efi_set_secure_boot(boot_params.secure_boot);
+
+ reserve_initrd();
+
+--- a/drivers/firmware/efi/Makefile
++++ b/drivers/firmware/efi/Makefile
+@@ -25,6 +25,7 @@ obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_m
+ obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o
+ obj-$(CONFIG_EFI_TEST) += test/
+ obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o
++obj-$(CONFIG_EFI) += secureboot.o
+ obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o
+ obj-$(CONFIG_EFI_RCI2_TABLE) += rci2-table.o
+ obj-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += embedded-firmware.o
+--- /dev/null
++++ b/drivers/firmware/efi/secureboot.c
+@@ -0,0 +1,39 @@
++
++/* Core kernel secure boot support.
++ *
++ * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
++ * Written by David Howells (dhowells@redhat.com)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public Licence
++ * as published by the Free Software Foundation; either version
++ * 2 of the Licence, or (at your option) any later version.
++ */
++
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
++#include <linux/efi.h>
++#include <linux/kernel.h>
++#include <linux/printk.h>
++
++/*
++ * Decide what to do when UEFI secure boot mode is enabled.
++ */
++void __init efi_set_secure_boot(enum efi_secureboot_mode mode)
++{
++ if (efi_enabled(EFI_BOOT)) {
++ switch (mode) {
++ case efi_secureboot_mode_disabled:
++ pr_info("Secure boot disabled\n");
++ break;
++ case efi_secureboot_mode_enabled:
++ set_bit(EFI_SECURE_BOOT, &efi.flags);
++ pr_info("Secure boot enabled\n");
++ break;
++ default:
++ pr_warn("Secure boot could not be determined (mode %u)\n",
++ mode);
++ break;
++ }
++ }
++}
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -776,6 +776,14 @@ extern int __init efi_setup_pcdp_console
+ #define EFI_MEM_ATTR 10 /* Did firmware publish an EFI_MEMORY_ATTRIBUTES table? */
+ #define EFI_MEM_NO_SOFT_RESERVE 11 /* Is the kernel configured to ignore soft reservations? */
+ #define EFI_PRESERVE_BS_REGIONS 12 /* Are EFI boot-services memory segments available? */
++#define EFI_SECURE_BOOT 13 /* Are we in Secure Boot mode? */
++
++enum efi_secureboot_mode {
++ efi_secureboot_mode_unset,
++ efi_secureboot_mode_unknown,
++ efi_secureboot_mode_disabled,
++ efi_secureboot_mode_enabled,
++};
+
+ #ifdef CONFIG_EFI
+ /*
+@@ -799,6 +807,7 @@ static inline bool efi_rt_services_suppo
+ {
+ return (efi.runtime_supported_mask & mask) == mask;
+ }
++extern void __init efi_set_secure_boot(enum efi_secureboot_mode mode);
+ #else
+ static inline bool efi_enabled(int feature)
+ {
+@@ -822,6 +831,7 @@ static inline bool efi_rt_services_suppo
+ {
+ return false;
+ }
++static inline void efi_set_secure_boot(enum efi_secureboot_mode mode) {}
+ #endif
+
+ extern int efi_status_to_err(efi_status_t status);
+@@ -1083,12 +1093,6 @@ static inline bool efi_runtime_disabled(
+ extern void efi_call_virt_check_flags(unsigned long flags, const char *call);
+ extern unsigned long efi_call_virt_save_flags(void);
+
+-enum efi_secureboot_mode {
+- efi_secureboot_mode_unset,
+- efi_secureboot_mode_unknown,
+- efi_secureboot_mode_disabled,
+- efi_secureboot_mode_enabled,
+-};
+ enum efi_secureboot_mode efi_get_secureboot(void);
+
+ #ifdef CONFIG_RESET_ATTACK_MITIGATION
diff --git a/debian/patches/features/all/lockdown/efi-lock-down-the-kernel-if-booted-in-secure-boot-mo.patch b/debian/patches/features/all/lockdown/efi-lock-down-the-kernel-if-booted-in-secure-boot-mo.patch
new file mode 100644
index 000000000..627e37154
--- /dev/null
+++ b/debian/patches/features/all/lockdown/efi-lock-down-the-kernel-if-booted-in-secure-boot-mo.patch
@@ -0,0 +1,127 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Tue, 10 Sep 2019 11:54:28 +0100
+Subject: efi: Lock down the kernel if booted in secure boot mode
+
+Based on an earlier patch by David Howells, who wrote the following
+description:
+
+> UEFI Secure Boot provides a mechanism for ensuring that the firmware will
+> only load signed bootloaders and kernels. Certain use cases may also
+> require that all kernel modules also be signed. Add a configuration option
+> that to lock down the kernel - which includes requiring validly signed
+> modules - if the kernel is secure-booted.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ arch/x86/kernel/setup.c | 4 ++--
+ drivers/firmware/efi/secureboot.c | 3 +++
+ include/linux/security.h | 6 ++++++
+ security/lockdown/Kconfig | 15 +++++++++++++++
+ security/lockdown/lockdown.c | 2 +-
+ 5 files changed, 27 insertions(+), 3 deletions(-)
+
+Index: debian-kernel/arch/x86/kernel/setup.c
+===================================================================
+--- debian-kernel.orig/arch/x86/kernel/setup.c
++++ debian-kernel/arch/x86/kernel/setup.c
+@@ -979,6 +979,8 @@ void __init setup_arch(char **cmdline_p)
+ if (efi_enabled(EFI_BOOT))
+ efi_init();
+
++ efi_set_secure_boot(boot_params.secure_boot);
++
+ dmi_setup();
+
+ /*
+@@ -1130,8 +1132,6 @@ void __init setup_arch(char **cmdline_p)
+ /* Allocate bigger log buffer */
+ setup_log_buf(1);
+
+- efi_set_secure_boot(boot_params.secure_boot);
+-
+ reserve_initrd();
+
+ acpi_table_upgrade();
+Index: debian-kernel/drivers/firmware/efi/secureboot.c
+===================================================================
+--- debian-kernel.orig/drivers/firmware/efi/secureboot.c
++++ debian-kernel/drivers/firmware/efi/secureboot.c
+@@ -15,6 +15,7 @@
+ #include <linux/efi.h>
+ #include <linux/kernel.h>
+ #include <linux/printk.h>
++#include <linux/security.h>
+
+ /*
+ * Decide what to do when UEFI secure boot mode is enabled.
+@@ -28,6 +29,10 @@ void __init efi_set_secure_boot(enum efi
+ break;
+ case efi_secureboot_mode_enabled:
+ set_bit(EFI_SECURE_BOOT, &efi.flags);
++#ifdef CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT
++ lock_kernel_down("EFI Secure Boot",
++ LOCKDOWN_INTEGRITY_MAX);
++#endif
+ pr_info("Secure boot enabled\n");
+ break;
+ default:
+Index: debian-kernel/include/linux/security.h
+===================================================================
+--- debian-kernel.orig/include/linux/security.h
++++ debian-kernel/include/linux/security.h
+@@ -451,6 +451,7 @@ int security_inode_notifysecctx(struct i
+ int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
+ int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
+ int security_locked_down(enum lockdown_reason what);
++int lock_kernel_down(const char *where, enum lockdown_reason level);
+ #else /* CONFIG_SECURITY */
+
+ static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data)
+@@ -1291,6 +1292,11 @@ static inline int security_locked_down(e
+ {
+ return 0;
+ }
++static inline int
++lock_kernel_down(const char *where, enum lockdown_reason level)
++{
++ return -EOPNOTSUPP;
++}
+ #endif /* CONFIG_SECURITY */
+
+ #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE)
+Index: debian-kernel/security/lockdown/Kconfig
+===================================================================
+--- debian-kernel.orig/security/lockdown/Kconfig
++++ debian-kernel/security/lockdown/Kconfig
+@@ -45,3 +45,18 @@ config LOCK_DOWN_KERNEL_FORCE_CONFIDENTI
+ disabled.
+
+ endchoice
++
++config LOCK_DOWN_IN_EFI_SECURE_BOOT
++ bool "Lock down the kernel in EFI Secure Boot mode"
++ default n
++ depends on SECURITY_LOCKDOWN_LSM
++ depends on EFI
++ select SECURITY_LOCKDOWN_LSM_EARLY
++ help
++ UEFI Secure Boot provides a mechanism for ensuring that the firmware
++ will only load signed bootloaders and kernels. Secure boot mode may
++ be determined from EFI variables provided by the system firmware if
++ not indicated by the boot parameters.
++
++ Enabling this option results in kernel lockdown being
++ triggered in confidentiality mode if EFI Secure Boot is set.
+Index: debian-kernel/security/lockdown/lockdown.c
+===================================================================
+--- debian-kernel.orig/security/lockdown/lockdown.c
++++ debian-kernel/security/lockdown/lockdown.c
+@@ -23,7 +23,7 @@ static const enum lockdown_reason lockdo
+ /*
+ * Put the kernel into lock-down mode.
+ */
+-static int lock_kernel_down(const char *where, enum lockdown_reason level)
++int lock_kernel_down(const char *where, enum lockdown_reason level)
+ {
+ if (kernel_locked_down >= level)
+ return -EPERM;
diff --git a/debian/patches/features/all/lockdown/mtd-disable-slram-and-phram-when-locked-down.patch b/debian/patches/features/all/lockdown/mtd-disable-slram-and-phram-when-locked-down.patch
new file mode 100644
index 000000000..5004e5dca
--- /dev/null
+++ b/debian/patches/features/all/lockdown/mtd-disable-slram-and-phram-when-locked-down.patch
@@ -0,0 +1,75 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Fri, 30 Aug 2019 15:54:24 +0100
+Subject: mtd: phram,slram: Disable when the kernel is locked down
+Forwarded: https://lore.kernel.org/linux-security-module/20190830154720.eekfjt6c4jzvlbfz@decadent.org.uk/
+
+These drivers allow mapping arbitrary memory ranges as MTD devices.
+This should be disabled to preserve the kernel's integrity when it is
+locked down.
+
+* Add the HWPARAM flag to the module parameters
+* When slram is built-in, it uses __setup() to read kernel parameters,
+ so add an explicit check security_locked_down() check
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Matthew Garrett <mjg59@google.com>
+Cc: David Howells <dhowells@redhat.com>
+Cc: Joern Engel <joern@lazybastard.org>
+Cc: linux-mtd@lists.infradead.org
+---
+ drivers/mtd/devices/phram.c | 6 +++++-
+ drivers/mtd/devices/slram.c | 9 ++++++++-
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/mtd/devices/phram.c
++++ b/drivers/mtd/devices/phram.c
+@@ -294,7 +294,11 @@ static int phram_param_call(const char *
+ #endif
+ }
+
+-module_param_call(phram, phram_param_call, NULL, NULL, 0200);
++static const struct kernel_param_ops phram_param_ops = {
++ .set = phram_param_call
++};
++__module_param_call(MODULE_PARAM_PREFIX, phram, &phram_param_ops, NULL,
++ 0200, -1, KERNEL_PARAM_FL_HWPARAM | hwparam_iomem);
+ MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>\"");
+
+
+--- a/drivers/mtd/devices/slram.c
++++ b/drivers/mtd/devices/slram.c
+@@ -43,6 +43,7 @@
+ #include <linux/ioctl.h>
+ #include <linux/init.h>
+ #include <linux/io.h>
++#include <linux/security.h>
+
+ #include <linux/mtd/mtd.h>
+
+@@ -65,7 +66,7 @@ typedef struct slram_mtd_list {
+ #ifdef MODULE
+ static char *map[SLRAM_MAX_DEVICES_PARAMS];
+
+-module_param_array(map, charp, NULL, 0);
++module_param_hw_array(map, charp, iomem, NULL, 0);
+ MODULE_PARM_DESC(map, "List of memory regions to map. \"map=<name>, <start>, <length / end>\"");
+ #else
+ static char *map;
+@@ -281,11 +282,17 @@ static int __init init_slram(void)
+ #ifndef MODULE
+ char *devstart;
+ char *devlength;
++ int ret;
+
+ if (!map) {
+ E("slram: not enough parameters.\n");
+ return(-EINVAL);
+ }
++
++ ret = security_locked_down(LOCKDOWN_MODULE_PARAMETERS);
++ if (ret)
++ return ret;
++
+ while (map) {
+ devname = devstart = devlength = NULL;
+
diff --git a/debian/patches/features/all/security-perf-allow-further-restriction-of-perf_event_open.patch b/debian/patches/features/all/security-perf-allow-further-restriction-of-perf_event_open.patch
new file mode 100644
index 000000000..33db1f765
--- /dev/null
+++ b/debian/patches/features/all/security-perf-allow-further-restriction-of-perf_event_open.patch
@@ -0,0 +1,80 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 11 Jan 2016 15:23:55 +0000
+Subject: security,perf: Allow further restriction of perf_event_open
+Forwarded: https://lkml.org/lkml/2016/1/11/587
+
+When kernel.perf_event_open is set to 3 (or greater), disallow all
+access to performance events by users without CAP_SYS_ADMIN.
+Add a Kconfig symbol CONFIG_SECURITY_PERF_EVENTS_RESTRICT that
+makes this value the default.
+
+This is based on a similar feature in grsecurity
+(CONFIG_GRKERNSEC_PERF_HARDEN). This version doesn't include making
+the variable read-only. It also allows enabling further restriction
+at run-time regardless of whether the default is changed.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ include/linux/perf_event.h | 5 +++++
+ kernel/events/core.c | 8 ++++++++
+ security/Kconfig | 9 +++++++++
+ 3 files changed, 22 insertions(+)
+
+--- a/include/linux/perf_event.h
++++ b/include/linux/perf_event.h
+@@ -1305,6 +1305,11 @@ int perf_cpu_time_max_percent_handler(st
+ int perf_event_max_stack_handler(struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos);
+
++static inline bool perf_paranoid_any(void)
++{
++ return sysctl_perf_event_paranoid > 2;
++}
++
+ /* Access to perf_event_open(2) syscall. */
+ #define PERF_SECURITY_OPEN 0
+
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -408,8 +408,13 @@ static cpumask_var_t perf_online_mask;
+ * 0 - disallow raw tracepoint access for unpriv
+ * 1 - disallow cpu events for unpriv
+ * 2 - disallow kernel profiling for unpriv
++ * 3 - disallow all unpriv perf event use
+ */
++#ifdef CONFIG_SECURITY_PERF_EVENTS_RESTRICT
++int sysctl_perf_event_paranoid __read_mostly = 3;
++#else
+ int sysctl_perf_event_paranoid __read_mostly = 2;
++#endif
+
+ /* Minimum for 512 kiB + 1 user control page */
+ int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' kiB per user */
+@@ -11785,6 +11790,9 @@ SYSCALL_DEFINE5(perf_event_open,
+ if (err)
+ return err;
+
++ if (perf_paranoid_any() && !capable(CAP_SYS_ADMIN))
++ return -EACCES;
++
+ /* Do we allow access to perf_event_open(2) ? */
+ err = security_perf_event_open(&attr, PERF_SECURITY_OPEN);
+ if (err)
+--- a/security/Kconfig
++++ b/security/Kconfig
+@@ -19,6 +19,15 @@ config SECURITY_DMESG_RESTRICT
+
+ If you are unsure how to answer this question, answer N.
+
++config SECURITY_PERF_EVENTS_RESTRICT
++ bool "Restrict unprivileged use of performance events"
++ depends on PERF_EVENTS
++ help
++ If you say Y here, the kernel.perf_event_paranoid sysctl
++ will be set to 3 by default, and no unprivileged use of the
++ perf_event_open syscall will be permitted unless it is
++ changed.
++
+ config SECURITY
+ bool "Enable different security models"
+ depends on SYSFS
diff --git a/debian/patches/features/arm64/arm64-compat-Implement-misalignment-fixups-for-multi.patch b/debian/patches/features/arm64/arm64-compat-Implement-misalignment-fixups-for-multi.patch
new file mode 100644
index 000000000..303e69f83
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-compat-Implement-misalignment-fixups-for-multi.patch
@@ -0,0 +1,480 @@
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Fri, 1 Jul 2022 15:53:22 +0200
+Subject: arm64: compat: Implement misalignment fixups for multiword loads
+Origin: https://git.kernel.org/linus/3fc24ef32d3b9368f4c103dcd21d6a3f959b4870
+
+The 32-bit ARM kernel implements fixups on behalf of user space when
+using LDM/STM or LDRD/STRD instructions on addresses that are not 32-bit
+aligned. This is not something that is supported by the architecture,
+but was done anyway to increase compatibility with user space software,
+which mostly targeted x86 at the time and did not care about aligned
+accesses.
+
+This feature is one of the remaining impediments to being able to switch
+to 64-bit kernels on 64-bit capable hardware running 32-bit user space,
+so let's implement it for the arm64 compat layer as well.
+
+Note that the intent is to implement the exact same handling of
+misaligned multi-word loads and stores as the 32-bit kernel does,
+including what appears to be missing support for user space programs
+that rely on SETEND to switch to a different byte order and back. Also,
+like the 32-bit ARM version, we rely on the faulting address reported by
+the CPU to infer the memory address, instead of decoding the instruction
+fully to obtain this information.
+
+This implementation is taken from the 32-bit ARM tree, with all pieces
+removed that deal with instructions other than LDRD/STRD and LDM/STM, or
+that deal with alignment exceptions taken in kernel mode.
+
+Cc: debian-arm@lists.debian.org
+Cc: Vagrant Cascadian <vagrant@debian.org>
+Cc: Riku Voipio <riku.voipio@iki.fi>
+Cc: Steve McIntyre <steve@einval.com>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Reviewed-by: Arnd Bergmann <arnd@arndb.de>
+Link: https://lore.kernel.org/r/20220701135322.3025321-1-ardb@kernel.org
+[catalin.marinas@arm.com: change the option to 'default n']
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+---
+ arch/arm64/Kconfig | 3 +
+ arch/arm64/include/asm/exception.h | 1 +
+ arch/arm64/kernel/Makefile | 1 +
+ arch/arm64/kernel/compat_alignment.c | 387 +++++++++++++++++++++++++++
+ arch/arm64/mm/fault.c | 3 +
+ 5 files changed, 395 insertions(+)
+ create mode 100644 arch/arm64/kernel/compat_alignment.c
+
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -1328,6 +1328,9 @@ config THUMB2_COMPAT_VDSO
+ Compile the compat vDSO with '-mthumb -fomit-frame-pointer' if y,
+ otherwise with '-marm'.
+
++config COMPAT_ALIGNMENT_FIXUPS
++ bool "Fix up misaligned multi-word loads and stores in user space"
++
+ menuconfig ARMV8_DEPRECATED
+ bool "Emulate deprecated/obsolete ARMv8 instructions"
+ depends on SYSCTL
+--- a/arch/arm64/include/asm/exception.h
++++ b/arch/arm64/include/asm/exception.h
+@@ -47,6 +47,7 @@ void do_el0_sys(unsigned long esr, struc
+ void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
+ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr);
+ void do_el0_cp15(unsigned long esr, struct pt_regs *regs);
++int do_compat_alignment_fixup(unsigned long addr, struct pt_regs *regs);
+ void do_el0_svc(struct pt_regs *regs);
+ void do_el0_svc_compat(struct pt_regs *regs);
+ void do_el0_fpac(struct pt_regs *regs, unsigned long esr);
+--- a/arch/arm64/kernel/Makefile
++++ b/arch/arm64/kernel/Makefile
+@@ -28,6 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
+ obj-$(CONFIG_COMPAT) += sys32.o signal32.o \
+ sys_compat.o
+ obj-$(CONFIG_COMPAT) += sigreturn32.o
++obj-$(CONFIG_COMPAT_ALIGNMENT_FIXUPS) += compat_alignment.o
+ obj-$(CONFIG_KUSER_HELPERS) += kuser32.o
+ obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
+ obj-$(CONFIG_MODULES) += module.o
+--- /dev/null
++++ b/arch/arm64/kernel/compat_alignment.c
+@@ -0,0 +1,387 @@
++// SPDX-License-Identifier: GPL-2.0-only
++// based on arch/arm/mm/alignment.c
++
++#include <linux/compiler.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/perf_event.h>
++#include <linux/uaccess.h>
++
++#include <asm/exception.h>
++#include <asm/ptrace.h>
++#include <asm/traps.h>
++
++/*
++ * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998
++ *
++ * Speed optimisations and better fault handling by Russell King.
++ */
++#define CODING_BITS(i) (i & 0x0e000000)
++
++#define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */
++#define LDST_U_BIT(i) (i & (1 << 23)) /* Add offset */
++#define LDST_W_BIT(i) (i & (1 << 21)) /* Writeback */
++#define LDST_L_BIT(i) (i & (1 << 20)) /* Load */
++
++#define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0)
++
++#define LDSTHD_I_BIT(i) (i & (1 << 22)) /* double/half-word immed */
++
++#define RN_BITS(i) ((i >> 16) & 15) /* Rn */
++#define RD_BITS(i) ((i >> 12) & 15) /* Rd */
++#define RM_BITS(i) (i & 15) /* Rm */
++
++#define REGMASK_BITS(i) (i & 0xffff)
++
++#define BAD_INSTR 0xdeadc0de
++
++/* Thumb-2 32 bit format per ARMv7 DDI0406A A6.3, either f800h,e800h,f800h */
++#define IS_T32(hi16) \
++ (((hi16) & 0xe000) == 0xe000 && ((hi16) & 0x1800))
++
++union offset_union {
++ unsigned long un;
++ signed long sn;
++};
++
++#define TYPE_ERROR 0
++#define TYPE_FAULT 1
++#define TYPE_LDST 2
++#define TYPE_DONE 3
++
++static void
++do_alignment_finish_ldst(unsigned long addr, u32 instr, struct pt_regs *regs,
++ union offset_union offset)
++{
++ if (!LDST_U_BIT(instr))
++ offset.un = -offset.un;
++
++ if (!LDST_P_BIT(instr))
++ addr += offset.un;
++
++ if (!LDST_P_BIT(instr) || LDST_W_BIT(instr))
++ regs->regs[RN_BITS(instr)] = addr;
++}
++
++static int
++do_alignment_ldrdstrd(unsigned long addr, u32 instr, struct pt_regs *regs)
++{
++ unsigned int rd = RD_BITS(instr);
++ unsigned int rd2;
++ int load;
++
++ if ((instr & 0xfe000000) == 0xe8000000) {
++ /* ARMv7 Thumb-2 32-bit LDRD/STRD */
++ rd2 = (instr >> 8) & 0xf;
++ load = !!(LDST_L_BIT(instr));
++ } else if (((rd & 1) == 1) || (rd == 14)) {
++ return TYPE_ERROR;
++ } else {
++ load = ((instr & 0xf0) == 0xd0);
++ rd2 = rd + 1;
++ }
++
++ if (load) {
++ unsigned int val, val2;
++
++ if (get_user(val, (u32 __user *)addr) ||
++ get_user(val2, (u32 __user *)(addr + 4)))
++ return TYPE_FAULT;
++ regs->regs[rd] = val;
++ regs->regs[rd2] = val2;
++ } else {
++ if (put_user(regs->regs[rd], (u32 __user *)addr) ||
++ put_user(regs->regs[rd2], (u32 __user *)(addr + 4)))
++ return TYPE_FAULT;
++ }
++ return TYPE_LDST;
++}
++
++/*
++ * LDM/STM alignment handler.
++ *
++ * There are 4 variants of this instruction:
++ *
++ * B = rn pointer before instruction, A = rn pointer after instruction
++ * ------ increasing address ----->
++ * | | r0 | r1 | ... | rx | |
++ * PU = 01 B A
++ * PU = 11 B A
++ * PU = 00 A B
++ * PU = 10 A B
++ */
++static int
++do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs)
++{
++ unsigned int rd, rn, nr_regs, regbits;
++ unsigned long eaddr, newaddr;
++ unsigned int val;
++
++ /* count the number of registers in the mask to be transferred */
++ nr_regs = hweight16(REGMASK_BITS(instr)) * 4;
++
++ rn = RN_BITS(instr);
++ newaddr = eaddr = regs->regs[rn];
++
++ if (!LDST_U_BIT(instr))
++ nr_regs = -nr_regs;
++ newaddr += nr_regs;
++ if (!LDST_U_BIT(instr))
++ eaddr = newaddr;
++
++ if (LDST_P_EQ_U(instr)) /* U = P */
++ eaddr += 4;
++
++ for (regbits = REGMASK_BITS(instr), rd = 0; regbits;
++ regbits >>= 1, rd += 1)
++ if (regbits & 1) {
++ if (LDST_L_BIT(instr)) {
++ if (get_user(val, (u32 __user *)eaddr))
++ return TYPE_FAULT;
++ if (rd < 15)
++ regs->regs[rd] = val;
++ else
++ regs->pc = val;
++ } else {
++ /*
++ * The PC register has a bias of +8 in ARM mode
++ * and +4 in Thumb mode. This means that a read
++ * of the value of PC should account for this.
++ * Since Thumb does not permit STM instructions
++ * to refer to PC, just add 8 here.
++ */
++ val = (rd < 15) ? regs->regs[rd] : regs->pc + 8;
++ if (put_user(val, (u32 __user *)eaddr))
++ return TYPE_FAULT;
++ }
++ eaddr += 4;
++ }
++
++ if (LDST_W_BIT(instr))
++ regs->regs[rn] = newaddr;
++
++ return TYPE_DONE;
++}
++
++/*
++ * Convert Thumb multi-word load/store instruction forms to equivalent ARM
++ * instructions so we can reuse ARM userland alignment fault fixups for Thumb.
++ *
++ * This implementation was initially based on the algorithm found in
++ * gdb/sim/arm/thumbemu.c. It is basically just a code reduction of same
++ * to convert only Thumb ld/st instruction forms to equivalent ARM forms.
++ *
++ * NOTES:
++ * 1. Comments below refer to ARM ARM DDI0100E Thumb Instruction sections.
++ * 2. If for some reason we're passed an non-ld/st Thumb instruction to
++ * decode, we return 0xdeadc0de. This should never happen under normal
++ * circumstances but if it does, we've got other problems to deal with
++ * elsewhere and we obviously can't fix those problems here.
++ */
++
++static unsigned long thumb2arm(u16 tinstr)
++{
++ u32 L = (tinstr & (1<<11)) >> 11;
++
++ switch ((tinstr & 0xf800) >> 11) {
++ /* 6.6.1 Format 1: */
++ case 0xc000 >> 11: /* 7.1.51 STMIA */
++ case 0xc800 >> 11: /* 7.1.25 LDMIA */
++ {
++ u32 Rn = (tinstr & (7<<8)) >> 8;
++ u32 W = ((L<<Rn) & (tinstr&255)) ? 0 : 1<<21;
++
++ return 0xe8800000 | W | (L<<20) | (Rn<<16) |
++ (tinstr&255);
++ }
++
++ /* 6.6.1 Format 2: */
++ case 0xb000 >> 11: /* 7.1.48 PUSH */
++ case 0xb800 >> 11: /* 7.1.47 POP */
++ if ((tinstr & (3 << 9)) == 0x0400) {
++ static const u32 subset[4] = {
++ 0xe92d0000, /* STMDB sp!,{registers} */
++ 0xe92d4000, /* STMDB sp!,{registers,lr} */
++ 0xe8bd0000, /* LDMIA sp!,{registers} */
++ 0xe8bd8000 /* LDMIA sp!,{registers,pc} */
++ };
++ return subset[(L<<1) | ((tinstr & (1<<8)) >> 8)] |
++ (tinstr & 255); /* register_list */
++ }
++ fallthrough; /* for illegal instruction case */
++
++ default:
++ return BAD_INSTR;
++ }
++}
++
++/*
++ * Convert Thumb-2 32 bit LDM, STM, LDRD, STRD to equivalent instruction
++ * handlable by ARM alignment handler, also find the corresponding handler,
++ * so that we can reuse ARM userland alignment fault fixups for Thumb.
++ *
++ * @pinstr: original Thumb-2 instruction; returns new handlable instruction
++ * @regs: register context.
++ * @poffset: return offset from faulted addr for later writeback
++ *
++ * NOTES:
++ * 1. Comments below refer to ARMv7 DDI0406A Thumb Instruction sections.
++ * 2. Register name Rt from ARMv7 is same as Rd from ARMv6 (Rd is Rt)
++ */
++static void *
++do_alignment_t32_to_handler(u32 *pinstr, struct pt_regs *regs,
++ union offset_union *poffset)
++{
++ u32 instr = *pinstr;
++ u16 tinst1 = (instr >> 16) & 0xffff;
++ u16 tinst2 = instr & 0xffff;
++
++ switch (tinst1 & 0xffe0) {
++ /* A6.3.5 Load/Store multiple */
++ case 0xe880: /* STM/STMIA/STMEA,LDM/LDMIA, PUSH/POP T2 */
++ case 0xe8a0: /* ...above writeback version */
++ case 0xe900: /* STMDB/STMFD, LDMDB/LDMEA */
++ case 0xe920: /* ...above writeback version */
++ /* no need offset decision since handler calculates it */
++ return do_alignment_ldmstm;
++
++ case 0xf840: /* POP/PUSH T3 (single register) */
++ if (RN_BITS(instr) == 13 && (tinst2 & 0x09ff) == 0x0904) {
++ u32 L = !!(LDST_L_BIT(instr));
++ const u32 subset[2] = {
++ 0xe92d0000, /* STMDB sp!,{registers} */
++ 0xe8bd0000, /* LDMIA sp!,{registers} */
++ };
++ *pinstr = subset[L] | (1<<RD_BITS(instr));
++ return do_alignment_ldmstm;
++ }
++ /* Else fall through for illegal instruction case */
++ break;
++
++ /* A6.3.6 Load/store double, STRD/LDRD(immed, lit, reg) */
++ case 0xe860:
++ case 0xe960:
++ case 0xe8e0:
++ case 0xe9e0:
++ poffset->un = (tinst2 & 0xff) << 2;
++ fallthrough;
++
++ case 0xe940:
++ case 0xe9c0:
++ return do_alignment_ldrdstrd;
++
++ /*
++ * No need to handle load/store instructions up to word size
++ * since ARMv6 and later CPUs can perform unaligned accesses.
++ */
++ default:
++ break;
++ }
++ return NULL;
++}
++
++static int alignment_get_arm(struct pt_regs *regs, __le32 __user *ip, u32 *inst)
++{
++ __le32 instr = 0;
++ int fault;
++
++ fault = get_user(instr, ip);
++ if (fault)
++ return fault;
++
++ *inst = __le32_to_cpu(instr);
++ return 0;
++}
++
++static int alignment_get_thumb(struct pt_regs *regs, __le16 __user *ip, u16 *inst)
++{
++ __le16 instr = 0;
++ int fault;
++
++ fault = get_user(instr, ip);
++ if (fault)
++ return fault;
++
++ *inst = __le16_to_cpu(instr);
++ return 0;
++}
++
++int do_compat_alignment_fixup(unsigned long addr, struct pt_regs *regs)
++{
++ union offset_union offset;
++ unsigned long instrptr;
++ int (*handler)(unsigned long addr, u32 instr, struct pt_regs *regs);
++ unsigned int type;
++ u32 instr = 0;
++ u16 tinstr = 0;
++ int isize = 4;
++ int thumb2_32b = 0;
++ int fault;
++
++ instrptr = instruction_pointer(regs);
++
++ if (compat_thumb_mode(regs)) {
++ __le16 __user *ptr = (__le16 __user *)(instrptr & ~1);
++
++ fault = alignment_get_thumb(regs, ptr, &tinstr);
++ if (!fault) {
++ if (IS_T32(tinstr)) {
++ /* Thumb-2 32-bit */
++ u16 tinst2;
++ fault = alignment_get_thumb(regs, ptr + 1, &tinst2);
++ instr = ((u32)tinstr << 16) | tinst2;
++ thumb2_32b = 1;
++ } else {
++ isize = 2;
++ instr = thumb2arm(tinstr);
++ }
++ }
++ } else {
++ fault = alignment_get_arm(regs, (__le32 __user *)instrptr, &instr);
++ }
++
++ if (fault)
++ return 1;
++
++ switch (CODING_BITS(instr)) {
++ case 0x00000000: /* 3.13.4 load/store instruction extensions */
++ if (LDSTHD_I_BIT(instr))
++ offset.un = (instr & 0xf00) >> 4 | (instr & 15);
++ else
++ offset.un = regs->regs[RM_BITS(instr)];
++
++ if ((instr & 0x001000f0) == 0x000000d0 || /* LDRD */
++ (instr & 0x001000f0) == 0x000000f0) /* STRD */
++ handler = do_alignment_ldrdstrd;
++ else
++ return 1;
++ break;
++
++ case 0x08000000: /* ldm or stm, or thumb-2 32bit instruction */
++ if (thumb2_32b) {
++ offset.un = 0;
++ handler = do_alignment_t32_to_handler(&instr, regs, &offset);
++ } else {
++ offset.un = 0;
++ handler = do_alignment_ldmstm;
++ }
++ break;
++
++ default:
++ return 1;
++ }
++
++ type = handler(addr, instr, regs);
++
++ if (type == TYPE_ERROR || type == TYPE_FAULT)
++ return 1;
++
++ if (type == TYPE_LDST)
++ do_alignment_finish_ldst(addr, instr, regs, offset);
++
++ perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, regs->pc);
++ arm64_skip_faulting_instruction(regs, isize);
++
++ return 0;
++}
+--- a/arch/arm64/mm/fault.c
++++ b/arch/arm64/mm/fault.c
+@@ -610,6 +610,9 @@ static int __kprobes do_translation_faul
+ static int do_alignment_fault(unsigned long addr, unsigned int esr,
+ struct pt_regs *regs)
+ {
++ if (IS_ENABLED(CONFIG_COMPAT_ALIGNMENT_FIXUPS) &&
++ compat_user_mode(regs))
++ return do_compat_alignment_fixup(addr, regs);
+ do_bad_area(addr, esr, regs);
+ return 0;
+ }
diff --git a/debian/patches/features/arm64/arm64-dts-raspberry-Add-support-for-the-CM4.patch b/debian/patches/features/arm64/arm64-dts-raspberry-Add-support-for-the-CM4.patch
new file mode 100644
index 000000000..8619cfcdd
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-raspberry-Add-support-for-the-CM4.patch
@@ -0,0 +1,423 @@
+From: Cyril Brulebois <cyril@debamax.com>
+Date: Mon, 03 Jan 2022 21:59:36 +0100
+Subject: arm64: dts: Add support for Raspberry Pi Compute Module 4 IO Board
+
+It was introduced in mainline during the v5.16 release cycle. Since
+many broadcom includes were reworked since v5.10, adding support would
+involve more than cherry-picking a DTS addition that uses a few
+includes.
+
+To avoid side effects on other models, introduce a DTS that leverages
+some existing includes (bcm2711.dtsi and bcm283x-rpi-usb-host.dtsi)
+and describes the rest without re-using parts of the Raspberry Pi 4 B
+model.
+
+To avoid phandle rotation (0x16, 0x17, and 0x18) across 3 nodes
+(dma@7e007000, i2c@7e205000, and interrupt-controller@7ef00100), and the
+related changes in other nodes referencing them, hardcode 0x16 as the
+phandle for interrupt-controller@7ef00100. This leads to an empty dtdiff
+between this new DTB and the one produced by a v5.16-rc8 build.
+
+Authored-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Reviewed-by: Cyril Brulebois <cyril@debamax.com>
+
+--- a/arch/arm64/boot/dts/broadcom/Makefile
++++ b/arch/arm64/boot/dts/broadcom/Makefile
+@@ -1,5 +1,6 @@
+ # SPDX-License-Identifier: GPL-2.0
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-4-b.dtb \
++ bcm2711-rpi-cm4-io.dtb \
+ bcm2837-rpi-3-a-plus.dtb \
+ bcm2837-rpi-3-b.dtb \
+ bcm2837-rpi-3-b-plus.dtb \
+--- /dev/null
++++ b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4-io.dts
+@@ -0,0 +1,2 @@
++// SPDX-License-Identifier: GPL-2.0
++#include "arm/bcm2711-rpi-cm4-io.dts"
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -93,6 +93,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+ bcm2837-rpi-3-b-plus.dtb \
+ bcm2837-rpi-cm3-io3.dtb \
+ bcm2711-rpi-4-b.dtb \
++ bcm2711-rpi-cm4-io.dtb \
+ bcm2835-rpi-zero.dtb \
+ bcm2835-rpi-zero-w.dtb
+ dtb-$(CONFIG_ARCH_BCM_5301X) += \
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4-io.dts
+@@ -0,0 +1,373 @@
++/dts-v1/;
++
++#include "bcm2711.dtsi"
++#include "bcm283x-rpi-usb-host.dtsi"
++
++/ {
++ model = "Raspberry Pi Compute Module 4 IO Board";
++ compatible = "raspberrypi,4-compute-module\0brcm,bcm2711";
++
++ aliases {
++ emmc2bus = "/emmc2bus";
++ ethernet0 = "/scb/ethernet@7d580000";
++ pcie0 = "/scb/pcie@7d500000";
++ blconfig = &blconfig;
++ };
++
++ chosen {
++ stdout-path = "serial1:115200n8";
++ };
++
++ leds {
++ compatible = "gpio-leds";
++
++ led-act {
++ label = "ACT";
++ default-state = "keep";
++ linux,default-trigger = "heartbeat";
++ gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
++ };
++
++ led-pwr {
++ label = "PWR";
++ gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
++ default-state = "keep";
++ linux,default-trigger = "default-on";
++ };
++ };
++
++ soc {
++ aon_intr: interrupt-controller@7ef00100 {
++ compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc";
++ reg = <0x7ef00100 0x30>;
++ phandle = <0x16>;
++ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-controller;
++ #interrupt-cells = <1>;
++ };
++
++ firmware: firmware {
++ compatible = "raspberrypi,bcm2835-firmware\0simple-mfd";
++ #address-cells = <0x01>;
++ #size-cells = <0x01>;
++ mboxes = <&mailbox>;
++ dma-ranges;
++
++ firmware_clocks: clocks {
++ compatible = "raspberrypi,firmware-clocks";
++ #clock-cells = <0x01>;
++ };
++
++ expgpio: gpio {
++ compatible = "raspberrypi,firmware-gpio";
++ gpio-controller;
++ #gpio-cells = <2>;
++ status = "okay";
++ gpio-line-names = "BT_ON", "WL_ON", "PWR_LED_OFF", "ANT1", "VDD_SD_IO_SEL", "CAM_GPIO", "SD_PWR_ON", "ANT2";
++ ant1-hog {
++ gpio-hog;
++ gpios = <0x03 0x00>;
++ output-high;
++ line-name = "ant1";
++ };
++
++ ant2-hog {
++ gpio-hog;
++ gpios = <0x07 0x00>;
++ output-low;
++ line-name = "ant2";
++ };
++ };
++
++ reset {
++ compatible = "raspberrypi,firmware-reset";
++ #reset-cells = <1>;
++ };
++ };
++
++ power: power {
++ compatible = "raspberrypi,bcm2835-power";
++ firmware = <&firmware>;
++ #power-domain-cells = <1>;
++ };
++
++ mailbox@7e00b840 {
++ compatible = "brcm,bcm2835-vchiq";
++ reg = <0x7e00b840 0x3c>;
++ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ vec@7ec13000 {
++ compatible = "brcm,bcm2711-vec";
++ reg = <0x7ec13000 0x1000>;
++ clocks = <&clocks BCM2835_CLOCK_VEC>;
++ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
++ status = "disabled";
++ power-domains = <&power /* RPI_POWER_DOMAIN_VEC = */ 7>;
++ };
++ };
++
++ memory@0 {
++ device_type = "memory";
++ reg = <0x00 0x00 0x00>;
++ };
++
++ wifi_pwrseq: wifi-pwrseq {
++ compatible = "mmc-pwrseq-simple";
++ reset-gpios = <&expgpio 0x01 0x01>;
++ };
++
++ sd_io_1v8_reg: sd_io_1v8_reg {
++ compatible = "regulator-gpio";
++ regulator-name = "vdd-sd-io";
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-boot-on;
++ regulator-always-on;
++ regulator-settling-time-us = <5000>;
++ gpios = <&expgpio 0x04 GPIO_ACTIVE_HIGH>;
++ states = <1800000 0x1>,
++ <3300000 0x0>;
++ status = "okay";
++ };
++
++ sd_vcc_reg: sd_vcc_reg {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc-sd";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-boot-on;
++ enable-active-high;
++ gpio = <&expgpio 6 GPIO_ACTIVE_HIGH>;
++ };
++};
++
++&ddc0 {
++ status = "okay";
++};
++
++&ddc1 {
++ status = "okay";
++};
++
++&dsi0 {
++ power-domains = <&power 17>;
++};
++
++&dsi1 {
++ compatible = "brcm,bcm2711-dsi1";
++ power-domains = <&power 18>;
++};
++
++&emmc2 {
++ status = "okay";
++ bus-width = <8>;
++ vqmmc-supply = <&sd_io_1v8_reg>;
++ vmmc-supply = <&sd_vcc_reg>;
++ broken-cd;
++ mmc-hs200-1_8v;
++};
++
++&gpio {
++ pinctrl-names = "default";
++ /*
++ * Parts taken from rpi_SCH_4b_4p0_reduced.pdf and
++ * the official GPU firmware DT blob.
++ *
++ * Legend:
++ * "FOO" = GPIO line named "FOO" on the schematic
++ * "FOO_N" = GPIO line named "FOO" on schematic, active low
++ */
++ gpio-line-names = "ID_SDA",
++ "ID_SCL",
++ "SDA1",
++ "SCL1",
++ "GPIO_GCLK",
++ "GPIO5",
++ "GPIO6",
++ "SPI_CE1_N",
++ "SPI_CE0_N",
++ "SPI_MISO",
++ "SPI_MOSI",
++ "SPI_SCLK",
++ "GPIO12",
++ "GPIO13",
++ /* Serial port */
++ "TXD1",
++ "RXD1",
++ "GPIO16",
++ "GPIO17",
++ "GPIO18",
++ "GPIO19",
++ "GPIO20",
++ "GPIO21",
++ "GPIO22",
++ "GPIO23",
++ "GPIO24",
++ "GPIO25",
++ "GPIO26",
++ "GPIO27",
++ "RGMII_MDIO",
++ "RGMIO_MDC",
++ /* Used by BT module */
++ "CTS0",
++ "RTS0",
++ "TXD0",
++ "RXD0",
++ /* Used by Wifi */
++ "SD1_CLK",
++ "SD1_CMD",
++ "SD1_DATA0",
++ "SD1_DATA1",
++ "SD1_DATA2",
++ "SD1_DATA3",
++ /* Shared with SPI flash */
++ "PWM0_MISO",
++ "PWM1_MOSI",
++ "STATUS_LED_G_CLK",
++ "SPIFLASH_CE_N",
++ "SDA0",
++ "SCL0",
++ "RGMII_RXCLK",
++ "RGMII_RXCTL",
++ "RGMII_RXD0",
++ "RGMII_RXD1",
++ "RGMII_RXD2",
++ "RGMII_RXD3",
++ "RGMII_TXCLK",
++ "RGMII_TXCTL",
++ "RGMII_TXD0",
++ "RGMII_TXD1",
++ "RGMII_TXD2",
++ "RGMII_TXD3";
++
++ gpioout {
++ brcm,pins = <0x06>;
++ brcm,function = <0x01>;
++ };
++
++ alt0 {
++ brcm,pins = <0x04 0x05 0x07 0x08 0x09 0x0a 0x0b>;
++ brcm,function = <0x04>;
++ };
++};
++
++&hdmi0 {
++ status = "okay";
++ interrupt-parent = <&aon_intr>;
++ interrupts = <0>, <1>, <2>, <3>, <4>, <5>;
++ interrupt-names = "cec-tx", "cec-rx", "cec-low", "wakeup", "hpd-connected", "hpd-removed";
++ clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 0>, <&clk_27MHz>;
++ wifi-2.4ghz-coexistence;
++};
++
++&hdmi1 {
++ status = "okay";
++ interrupt-parent = <&aon_intr>;
++ interrupts = <8>, <7>, <6>, <9>, <10>, <11>;
++ interrupt-names = "cec-tx", "cec-rx", "cec-low", "wakeup", "hpd-connected", "hpd-removed";
++ clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 1>, <&clk_27MHz>;
++ wifi-2.4ghz-coexistence;
++};
++
++&hvs {
++ clocks = <&firmware_clocks 4>;
++};
++
++&i2c0 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c0_gpio0>;
++ clock-frequency = <100000>;
++};
++
++&i2c1 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c1_gpio2>;
++ clock-frequency = <100000>;
++};
++
++&genet {
++ status = "okay";
++ phy-handle = <&ethphy0>;
++ phy-mode = "rgmii-rxid";
++};
++
++&genet_mdio {
++ ethphy0: ethernet-phy@0 {
++ reg = <0>;
++ };
++};
++
++&pixelvalve0 {
++ status = "okay";
++};
++
++&pixelvalve1 {
++ status = "okay";
++};
++
++&pixelvalve2 {
++ status = "okay";
++};
++
++&pixelvalve4 {
++ status = "okay";
++};
++
++&rmem {
++ blconfig: nvram@0 {
++ compatible = "raspberrypi,bootloader-config", "nvmem-rmem";
++ #address-cells = <0x01>;
++ #size-cells = <0x01>;
++ reg = <0x00 0x00 0x00>;
++ no-map;
++ status = "disabled";
++ };
++};
++
++&sdhci {
++ status = "okay";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&emmc_gpio34>;
++ bus-width = <4>;
++ non-removable;
++ mmc-pwrseq = <&wifi_pwrseq>;
++
++ wifi@1 {
++ reg = <0x01>;
++ compatible = "brcm,bcm4329-fmac";
++ };
++};
++
++&uart0 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart0_ctsrts_gpio30 &uart0_gpio32>;
++ uart-has-rtscts;
++
++ bluetooth {
++ compatible = "brcm,bcm43438-bt";
++ max-speed = <0x1e8480>;
++ shutdown-gpios = <&expgpio 0x00 0x00>;
++ };
++};
++
++&uart1 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart1_gpio14>;
++};
++
++&usb {
++ power-domains = <&power 6>;
++};
++
++&vc4 {
++ status = "okay";
++};
++
++/delete-node/ &vec;
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Add-basic-support-for-Kobol-s-Hel.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Add-basic-support-for-Kobol-s-Hel.patch
new file mode 100644
index 000000000..deeed7034
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Add-basic-support-for-Kobol-s-Hel.patch
@@ -0,0 +1,419 @@
+From: Uwe Kleine-König <uwe@kleine-koenig.org>
+Date: Wed, 14 Oct 2020 22:00:30 +0200
+Subject: arm64: dts: rockchip: Add basic support for Kobol's Helios64
+Origin: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/patch/?id=09e006cfb43e8ec38afe28278b210dab72e6cac8
+
+The hardware is described in detail on Kobol's wiki at
+https://wiki.kobol.io/helios64/intro/.
+
+Up to now the following peripherals are working:
+
+ - UART
+ - Micro-SD card
+ - eMMC
+ - ethernet port 1
+ - status LED
+ - temperature sensor on i2c bus 2
+
+Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org>
+Link: https://lore.kernel.org/r/20201014200030.845759-3-uwe@kleine-koenig.org
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ arch/arm64/boot/dts/rockchip/Makefile | 1 +
+ .../dts/rockchip/rk3399-kobol-helios64.dts | 372 ++++++++++++++++++
+ 2 files changed, 373 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
+
+diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
+index 26661c7b736b..28b26a874313 100644
+--- a/arch/arm64/boot/dts/rockchip/Makefile
++++ b/arch/arm64/boot/dts/rockchip/Makefile
+@@ -26,6 +26,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-hugsun-x99.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-khadas-edge.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-khadas-edge-captain.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-khadas-edge-v.dtb
++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-kobol-helios64.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-leez-p710.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopc-t4.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-m4.dtb
+diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
+new file mode 100644
+index 000000000000..2a561be724b2
+--- /dev/null
++++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
+@@ -0,0 +1,372 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Copyright (c) 2020 Aditya Prayoga <aditya@kobol.io>
++ */
++
++/*
++ * The Kobol Helios64 is a board designed to operate as a NAS and optionally
++ * ships with an enclosing that can host five 2.5" hard disks.
++ *
++ * See https://wiki.kobol.io/helios64/intro/ for further details.
++ */
++
++/dts-v1/;
++#include "rk3399.dtsi"
++#include "rk3399-opp.dtsi"
++
++/ {
++ model = "Kobol Helios64";
++ compatible = "kobol,helios64", "rockchip,rk3399";
++
++ avdd_1v8_s0: avdd-1v8-s0 {
++ compatible = "regulator-fixed";
++ regulator-name = "avdd_1v8_s0";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++ vin-supply = <&vcc3v3_sys_s3>;
++ };
++
++ clkin_gmac: external-gmac-clock {
++ compatible = "fixed-clock";
++ clock-frequency = <125000000>;
++ clock-output-names = "clkin_gmac";
++ #clock-cells = <0>;
++ };
++
++ leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&sys_grn_led_on &sys_red_led_on>;
++
++ led-0 {
++ label = "helios64:green:status";
++ gpios = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>;
++ default-state = "on";
++ };
++
++ led-1 {
++ label = "helios64:red:fault";
++ gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>;
++ default-state = "keep";
++ };
++ };
++
++ vcc1v8_sys_s0: vcc1v8-sys-s0 {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc1v8_sys_s0";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++ vin-supply = <&vcc1v8_sys_s3>;
++ };
++
++ vcc3v0_sd: vcc3v0-sd {
++ compatible = "regulator-fixed";
++ enable-active-high;
++ gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>;
++ regulator-name = "vcc3v0_sd";
++ regulator-boot-on;
++ regulator-min-microvolt = <3000000>;
++ regulator-max-microvolt = <3000000>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&sdmmc0_pwr_h>;
++ vin-supply = <&vcc3v3_sys_s3>;
++ };
++
++ vcc3v3_sys_s3: vcc_lan: vcc3v3-sys-s3 {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc3v3_sys_s3";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ vin-supply = <&vcc5v0_sys>;
++
++ regulator-state-mem {
++ regulator-on-in-suspend;
++ };
++ };
++
++ vcc5v0_sys: vcc5v0-sys {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc5v0_sys";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ vin-supply = <&vcc12v_dcin_bkup>;
++
++ regulator-state-mem {
++ regulator-on-in-suspend;
++ };
++ };
++
++ vcc12v_dcin: vcc12v-dcin {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc12v_dcin";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <12000000>;
++ regulator-max-microvolt = <12000000>;
++ };
++
++ vcc12v_dcin_bkup: vcc12v-dcin-bkup {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc12v_dcin_bkup";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <12000000>;
++ regulator-max-microvolt = <12000000>;
++ vin-supply = <&vcc12v_dcin>;
++ };
++};
++
++/*
++ * The system doesn't run stable with cpu freq enabled, so disallow the lower
++ * frequencies until this problem is properly understood and resolved.
++ */
++&cluster0_opp {
++ /delete-node/ opp00;
++ /delete-node/ opp01;
++ /delete-node/ opp02;
++ /delete-node/ opp03;
++ /delete-node/ opp04;
++};
++
++&cluster1_opp {
++ /delete-node/ opp00;
++ /delete-node/ opp01;
++ /delete-node/ opp02;
++ /delete-node/ opp03;
++ /delete-node/ opp04;
++ /delete-node/ opp05;
++ /delete-node/ opp06;
++};
++
++&cpu_b0 {
++ cpu-supply = <&vdd_cpu_b>;
++};
++
++&cpu_b1 {
++ cpu-supply = <&vdd_cpu_b>;
++};
++
++&cpu_l0 {
++ cpu-supply = <&vdd_cpu_l>;
++};
++
++&cpu_l1 {
++ cpu-supply = <&vdd_cpu_l>;
++};
++
++&cpu_l2 {
++ cpu-supply = <&vdd_cpu_l>;
++};
++
++&cpu_l3 {
++ cpu-supply = <&vdd_cpu_l>;
++};
++
++&emmc_phy {
++ status = "okay";
++};
++
++&gmac {
++ assigned-clock-parents = <&clkin_gmac>;
++ assigned-clocks = <&cru SCLK_RMII_SRC>;
++ clock_in_out = "input";
++ phy-mode = "rgmii";
++ phy-supply = <&vcc_lan>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&rgmii_pins &gphy_reset>;
++ rx_delay = <0x20>;
++ tx_delay = <0x28>;
++ snps,reset-active-low;
++ snps,reset-delays-us = <0 10000 50000>;
++ snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
++ status = "okay";
++};
++
++&i2c0 {
++ clock-frequency = <400000>;
++ i2c-scl-rising-time-ns = <168>;
++ i2c-scl-falling-time-ns = <4>;
++ status = "okay";
++
++ rk808: pmic@1b {
++ compatible = "rockchip,rk808";
++ reg = <0x1b>;
++ interrupt-parent = <&gpio0>;
++ interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
++ clock-output-names = "xin32k", "rk808-clkout2";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pmic_int_l>;
++ vcc1-supply = <&vcc5v0_sys>;
++ vcc2-supply = <&vcc5v0_sys>;
++ vcc3-supply = <&vcc5v0_sys>;
++ vcc4-supply = <&vcc5v0_sys>;
++ vcc6-supply = <&vcc5v0_sys>;
++ vcc7-supply = <&vcc5v0_sys>;
++ vcc8-supply = <&vcc3v3_sys_s3>;
++ vcc9-supply = <&vcc5v0_sys>;
++ vcc10-supply = <&vcc5v0_sys>;
++ vcc11-supply = <&vcc5v0_sys>;
++ vcc12-supply = <&vcc3v3_sys_s3>;
++ vddio-supply = <&vcc3v0_s3>;
++ wakeup-source;
++ #clock-cells = <1>;
++
++ regulators {
++ vdd_cpu_l: DCDC_REG2 {
++ regulator-name = "vdd_cpu_l";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <750000>;
++ regulator-max-microvolt = <1350000>;
++ regulator-ramp-delay = <6001>;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++
++ vcc1v8_sys_s3: DCDC_REG4 {
++ regulator-name = "vcc1v8_sys_s3";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++
++ regulator-state-mem {
++ regulator-on-in-suspend;
++ regulator-suspend-microvolt = <1800000>;
++ };
++ };
++
++ vcc_sdio_s0: LDO_REG4 {
++ regulator-name = "vcc_sdio_s0";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3000000>;
++
++ regulator-state-mem {
++ regulator-on-in-suspend;
++ regulator-suspend-microvolt = <3000000>;
++ };
++ };
++
++ vcc3v0_s3: LDO_REG8 {
++ regulator-name = "vcc3v0_s3";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <3000000>;
++ regulator-max-microvolt = <3000000>;
++
++ regulator-state-mem {
++ regulator-on-in-suspend;
++ regulator-suspend-microvolt = <3000000>;
++ };
++ };
++ };
++ };
++
++ vdd_cpu_b: regulator@40 {
++ compatible = "silergy,syr827";
++ reg = <0x40>;
++ fcs,suspend-voltage-selector = <1>;
++ regulator-name = "vdd_cpu_b";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <712500>;
++ regulator-max-microvolt = <1500000>;
++ regulator-ramp-delay = <1000>;
++ vin-supply = <&vcc5v0_sys>;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++};
++
++&i2c2 {
++ clock-frequency = <400000>;
++ i2c-scl-rising-time-ns = <160>;
++ i2c-scl-falling-time-ns = <30>;
++ status = "okay";
++
++ temp@4c {
++ compatible = "national,lm75";
++ reg = <0x4c>;
++ };
++};
++
++&io_domains {
++ audio-supply = <&vcc1v8_sys_s0>;
++ bt656-supply = <&vcc1v8_sys_s0>;
++ gpio1830-supply = <&vcc3v0_s3>;
++ sdmmc-supply = <&vcc_sdio_s0>;
++ status = "okay";
++};
++
++&pinctrl {
++ gmac {
++ gphy_reset: gphy-reset {
++ rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_output_low>;
++ };
++ };
++
++ leds {
++ sys_grn_led_on: sys-grn-led-on {
++ rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>;
++ };
++
++ sys_red_led_on: sys-red-led-on {
++ rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>;
++ };
++ };
++
++ pmic {
++ pmic_int_l: pmic-int-l {
++ rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
++ };
++ };
++
++ vcc3v0-sd {
++ sdmmc0_pwr_h: sdmmc0-pwr-h {
++ rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>;
++ };
++ };
++};
++
++&pmu_io_domains {
++ pmu1830-supply = <&vcc3v0_s3>;
++ status = "okay";
++};
++
++&sdhci {
++ bus-width = <8>;
++ mmc-hs200-1_8v;
++ non-removable;
++ vqmmc-supply = <&vcc1v8_sys_s0>;
++ status = "okay";
++};
++
++&sdmmc {
++ bus-width = <4>;
++ cap-sd-highspeed;
++ cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
++ disable-wp;
++ pinctrl-names = "default";
++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
++ vmmc-supply = <&vcc3v0_sd>;
++ vqmmc-supply = <&vcc_sdio_s0>;
++ status = "okay";
++};
++
++&uart2 {
++ status = "okay";
++};
+--
+2.28.0
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-PCIe-on-helios64.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-PCIe-on-helios64.patch
new file mode 100644
index 000000000..6abebd080
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-PCIe-on-helios64.patch
@@ -0,0 +1,113 @@
+From: Uwe Kleine-König <uwe@kleine-koenig.org>
+Date: Mon, 10 May 2021 11:09:32 +0200
+Subject: arm64: dts: rockchip: Add support for PCIe on helios64
+Origin: https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git/patch/?id=5a65adfa2ad1542f856fc7de3999d51f3a35d2e2
+
+This is enough to make the SATA controller visible:
+
+# lspci
+00:00.0 PCI bridge: Fuzhou Rockchip Electronics Co., Ltd RK3399 PCI Express Root Port
+01:00.0 SATA controller: JMicron Technology Corp. JMB58x AHCI SATA controller
+
+Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org>
+Link: https://lore.kernel.org/r/20210510090932.970447-1-uwe@kleine-koenig.org
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ .../dts/rockchip/rk3399-kobol-helios64.dts | 53 +++++++++++++++++++
+ 1 file changed, 53 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
+index 9d4a0885fd12..037dc5cdc3f3 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
+@@ -23,6 +23,16 @@ aliases {
+ mmc1 = &sdhci;
+ };
+
++ avdd_0v9_s0: avdd-0v9-s0 {
++ compatible = "regulator-fixed";
++ regulator-name = "avdd_0v9_s0";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <900000>;
++ regulator-max-microvolt = <900000>;
++ vin-supply = <&vcc1v8_sys_s3>;
++ };
++
+ avdd_1v8_s0: avdd-1v8-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "avdd_1v8_s0";
+@@ -72,6 +82,18 @@ led-1 {
+ };
+ };
+
++ pcie_power: pcie-power {
++ compatible = "regulator-fixed";
++ enable-active-high;
++ gpio = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>;
++ pinctrl-0 = <&pcie_pwr>;
++ pinctrl-names = "default";
++ regulator-boot-on;
++ regulator-name = "pcie_power";
++ startup-delay-us = <10000>;
++ vin-supply = <&vcc5v0_perdev>;
++ };
++
+ vcc1v8_sys_s0: vcc1v8-sys-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc1v8_sys_s0";
+@@ -109,6 +131,16 @@ regulator-state-mem {
+ };
+ };
+
++ vcc5v0_perdev: vcc5v0-perdev {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc5v0_perdev";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ vin-supply = <&vcc12v_dcin_bkup>;
++ };
++
+ vcc5v0_sys: vcc5v0-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+@@ -331,6 +363,20 @@ &io_domains {
+ status = "okay";
+ };
+
++&pcie_phy {
++ status = "okay";
++};
++
++&pcie0 {
++ num-lanes = <2>;
++ status = "okay";
++
++ vpcie12v-supply = <&vcc12v_dcin>;
++ vpcie3v3-supply = <&pcie_power>;
++ vpcie1v8-supply = <&avdd_1v8_s0>;
++ vpcie0v9-supply = <&avdd_0v9_s0>;
++};
++
+ &pinctrl {
+ gmac {
+ gphy_reset: gphy-reset {
+@@ -348,6 +394,13 @@ sys_red_led_on: sys-red-led-on {
+ };
+ };
+
++ pcie {
++ pcie_pwr: pcie-pwr {
++ rockchip,pins =
++ <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
++ };
++ };
++
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+--
+2.30.2
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-two-PWM-fans-on-h.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-two-PWM-fans-on-h.patch
new file mode 100644
index 000000000..9755e0b8c
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-two-PWM-fans-on-h.patch
@@ -0,0 +1,61 @@
+From: Uwe Kleine-König <uwe@kleine-koenig.org>
+Date: Mon, 10 May 2021 11:06:07 +0200
+Subject: arm64: dts: rockchip: Add support for two PWM fans on
+ helios64
+Origin: https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git/patch/?id=271b66414df0b172c936b3cfd1894b7939f84165
+
+On the helios64 board the two connectors P6 and P7 are supposed to
+power two fans. Add the corresponding pwm-fan devices.
+
+Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org>
+Link: https://lore.kernel.org/r/20210510090607.970145-1-uwe@kleine-koenig.org
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ .../dts/rockchip/rk3399-kobol-helios64.dts | 24 +++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
+index 19485b552bc4..9d4a0885fd12 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
+@@ -40,6 +40,20 @@ clkin_gmac: external-gmac-clock {
+ #clock-cells = <0>;
+ };
+
++ fan1 {
++ /* fan connected to P7 */
++ compatible = "pwm-fan";
++ pwms = <&pwm0 0 40000 0>;
++ cooling-levels = <0 80 170 255>;
++ };
++
++ fan2 {
++ /* fan connected to P6 */
++ compatible = "pwm-fan";
++ pwms = <&pwm1 0 40000 0>;
++ cooling-levels = <0 80 170 255>;
++ };
++
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+@@ -352,6 +366,16 @@ &pmu_io_domains {
+ status = "okay";
+ };
+
++&pwm0 {
++ /* pwm-fan on P7 */
++ status = "okay";
++};
++
++&pwm1 {
++ /* pwm-fan on P6 */
++ status = "okay";
++};
++
+ &sdhci {
+ bus-width = <8>;
+ mmc-hs200-1_8v;
+--
+2.30.2
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Rely-on-SoC-external-pull-up-on-p.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Rely-on-SoC-external-pull-up-on-p.patch
new file mode 100644
index 000000000..ef6dab336
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Rely-on-SoC-external-pull-up-on-p.patch
@@ -0,0 +1,32 @@
+From: Uwe Kleine-König <uwe@kleine-koenig.org>
+Date: Sun, 24 Jan 2021 22:03:28 +0100
+Subject: arm64: dts: rockchip: Rely on SoC external pull up on pmic-int-l on Helios64
+Origin: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/patch/?id=1e58ba111421375c5948c3e8145bdd84b06ac095
+
+According to the schematic there is an external pull up, so there is no
+need to enable the internal one additionally. Using no pull up matches
+the vendor device tree.
+
+Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org>
+Link: https://lore.kernel.org/r/20210124210328.611707-2-uwe@kleine-koenig.org
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
+index 2a561be724b2..66c725a34220 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
+@@ -331,7 +331,7 @@ sys_red_led_on: sys-red-led-on {
+
+ pmic {
+ pmic_int_l: pmic-int-l {
+- rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
++ rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+--
+2.30.2
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-kobol-helios64-Add-mmc-aliases.patch b/debian/patches/features/arm64/arm64-dts-rockchip-kobol-helios64-Add-mmc-aliases.patch
new file mode 100644
index 000000000..ad4b53de9
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-kobol-helios64-Add-mmc-aliases.patch
@@ -0,0 +1,30 @@
+From: Uwe Kleine-König <ukleinek@debian.org>
+Date: Wed, 29 Mar 2021 09:45:58 +0100
+Subject: arm64: dts: rockchip: kobol-helios64: Add mmc aliases
+
+This patch is part of commit 5dcbe7e3862d ("arm64: dts: rockchip: move mmc
+aliases to board dts on rk3399") upstream. It is applied here only for Kobol's
+helios64 to simplify conflict resolution for some further patches. It currently
+is a noop as the same aliases already exist in rk3399.dtsi.
+
+Link: https://lore.kernel.org/r/20210324122235.1059292-7-heiko@sntech.de
+---
+diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
+index 66c725a34220..19485b552bc4 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
+@@ -18,6 +18,11 @@ / {
+ model = "Kobol Helios64";
+ compatible = "kobol,helios64", "rockchip,rk3399";
+
++ aliases {
++ mmc0 = &sdmmc;
++ mmc1 = &sdhci;
++ };
++
+ avdd_1v8_s0: avdd-1v8-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "avdd_1v8_s0";
+--
+2.30.2
+
diff --git a/debian/patches/features/x86/intel-iommu-add-kconfig-option-to-exclude-igpu-by-default.patch b/debian/patches/features/x86/intel-iommu-add-kconfig-option-to-exclude-igpu-by-default.patch
new file mode 100644
index 000000000..1840fc4bd
--- /dev/null
+++ b/debian/patches/features/x86/intel-iommu-add-kconfig-option-to-exclude-igpu-by-default.patch
@@ -0,0 +1,85 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 21 Aug 2019 00:32:16 +0100
+Subject: intel-iommu: Add Kconfig option to exclude iGPU by default
+Bug-Debian: https://bugs.debian.org/935270
+Bug-Kali: https://bugs.kali.org/view.php?id=5644
+
+There is still laptop firmware that touches the integrated GPU behind
+the operating system's back, and doesn't say so in the RMRR table.
+Enabling the IOMMU for all devices causes breakage.
+
+Replace CONFIG_INTEL_IOMMU_DEFAULT_ON with a 3-way choice
+corresponding to "on", "off", and "on,intgpu_off".
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/drivers/iommu/intel/Kconfig
++++ b/drivers/iommu/intel/Kconfig
+@@ -45,14 +45,28 @@ config INTEL_IOMMU_SVM
+ to access DMA resources through process address space by
+ means of a Process Address Space ID (PASID).
+
+-config INTEL_IOMMU_DEFAULT_ON
+- def_bool y
+- prompt "Enable Intel DMA Remapping Devices by default"
+- depends on INTEL_IOMMU
++if INTEL_IOMMU
++
++choice
++ prompt "Default state of Intel DMA Remapping Devices"
++ default INTEL_IOMMU_DEFAULT_ON
+ help
+- Selecting this option will enable a DMAR device at boot time if
+- one is found. If this option is not selected, DMAR support can
+- be enabled by passing intel_iommu=on to the kernel.
++ Choose whether Intel DMA Remapping Devices should be enabled
++ by default. This can be overridden at boot time using the
++ intel_iommu= kernel parameter.
++
++config INTEL_IOMMU_DEFAULT_ON
++ bool "Enable"
++
++config INTEL_IOMMU_DEFAULT_ON_INTGPU_OFF
++ bool "Enable, excluding integrated GPU"
++
++config INTEL_IOMMU_DEFAULT_OFF
++ bool "Disable"
++
++endchoice
++
++endif
+
+ config INTEL_IOMMU_BROKEN_GFX_WA
+ bool "Workaround broken graphics drivers (going away soon)"
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -338,11 +338,7 @@ static int intel_iommu_attach_device(str
+ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
+ dma_addr_t iova);
+
+-#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
+-int dmar_disabled = 0;
+-#else
+-int dmar_disabled = 1;
+-#endif /* CONFIG_INTEL_IOMMU_DEFAULT_ON */
++int dmar_disabled = IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_OFF);
+
+ #ifdef CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON
+ int intel_iommu_sm = 1;
+@@ -354,7 +350,7 @@ int intel_iommu_enabled = 0;
+ EXPORT_SYMBOL_GPL(intel_iommu_enabled);
+
+ static int dmar_map_gfx = 1;
+-static int dmar_map_intgpu = 1;
++static int dmar_map_intgpu = IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON);
+ static int dmar_forcedac;
+ static int intel_iommu_strict;
+ static int intel_iommu_superpage = 1;
+@@ -442,6 +438,7 @@ static int __init intel_iommu_setup(char
+ while (*str) {
+ if (!strncmp(str, "on", 2)) {
+ dmar_disabled = 0;
++ dmar_map_intgpu = 1;
+ pr_info("IOMMU enabled\n");
+ } else if (!strncmp(str, "off", 3)) {
+ dmar_disabled = 1;
diff --git a/debian/patches/features/x86/intel-iommu-add-option-to-exclude-integrated-gpu-only.patch b/debian/patches/features/x86/intel-iommu-add-option-to-exclude-integrated-gpu-only.patch
new file mode 100644
index 000000000..1717d8fe2
--- /dev/null
+++ b/debian/patches/features/x86/intel-iommu-add-option-to-exclude-integrated-gpu-only.patch
@@ -0,0 +1,91 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 21 Aug 2019 00:05:30 +0100
+Subject: intel-iommu: Add option to exclude integrated GPU only
+Bug-Debian: https://bugs.debian.org/935270
+Bug-Kali: https://bugs.kali.org/view.php?id=5644
+
+There is still laptop firmware that touches the integrated GPU behind
+the operating system's back, and doesn't say so in the RMRR table.
+Enabling the IOMMU for all devices causes breakage, but turning it off
+for all graphics devices seems like a major weakness.
+
+Add an option, intel_iommu=igpu_off, to exclude only integrated GPUs
+from remapping. This is a narrower exclusion than igfx_off: it only
+affects Intel devices on the root bus. Devices attached through an
+external port (Thunderbolt or ExpressCard) won't be on the root bus.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ Documentation/admin-guide/kernel-parameters.txt | 2 ++
+ drivers/iommu/intel/iommu.c | 14 ++++++++++++++
+ 2 files changed, 16 insertions(+)
+
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -1837,6 +1837,8 @@
+ bypassed by not enabling DMAR with this option. In
+ this case, gfx device will use physical address for
+ DMA.
++ intgpu_off [Default Off]
++ Bypass the DMAR unit for an integrated GPU only.
+ forcedac [X86-64]
+ With this option iommu will not optimize to look
+ for io virtual address below 32-bit forcing dual
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -54,6 +54,9 @@
+ #define CONTEXT_SIZE VTD_PAGE_SIZE
+
+ #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
++#define IS_INTGPU_DEVICE(pdev) (IS_GFX_DEVICE(pdev) && \
++ (pdev)->vendor == 0x8086 && \
++ pci_is_root_bus((pdev)->bus))
+ #define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
+ #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
+ #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
+@@ -351,6 +354,7 @@ int intel_iommu_enabled = 0;
+ EXPORT_SYMBOL_GPL(intel_iommu_enabled);
+
+ static int dmar_map_gfx = 1;
++static int dmar_map_intgpu = 1;
+ static int dmar_forcedac;
+ static int intel_iommu_strict;
+ static int intel_iommu_superpage = 1;
+@@ -360,6 +364,7 @@ static int iommu_skip_te_disable;
+
+ #define IDENTMAP_GFX 2
+ #define IDENTMAP_AZALIA 4
++#define IDENTMAP_INTGPU 8
+
+ int intel_iommu_gfx_mapped;
+ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
+@@ -445,6 +450,9 @@ static int __init intel_iommu_setup(char
+ } else if (!strncmp(str, "igfx_off", 8)) {
+ dmar_map_gfx = 0;
+ pr_info("Disable GFX device mapping\n");
++ } else if (!strncmp(str, "intgpu_off", 8)) {
++ dmar_map_intgpu = 0;
++ pr_info("Disable integrated GPU device mapping\n");
+ } else if (!strncmp(str, "forcedac", 8)) {
+ pr_info("Forcing DAC for PCI devices\n");
+ dmar_forcedac = 1;
+@@ -2890,6 +2898,9 @@ static int device_def_domain_type(struct
+
+ if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
+ return IOMMU_DOMAIN_IDENTITY;
++
++ if ((iommu_identity_mapping & IDENTMAP_INTGPU) && IS_INTGPU_DEVICE(pdev))
++ return IOMMU_DOMAIN_IDENTITY;
+ }
+
+ return 0;
+@@ -3325,6 +3336,9 @@ static int __init init_dmars(void)
+ if (!dmar_map_gfx)
+ iommu_identity_mapping |= IDENTMAP_GFX;
+
++ if (!dmar_map_intgpu)
++ iommu_identity_mapping |= IDENTMAP_INTGPU;
++
+ check_tylersburg_isoch();
+
+ ret = si_domain_init(hw_pass_through);
diff --git a/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch b/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch
new file mode 100644
index 000000000..62731a997
--- /dev/null
+++ b/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch
@@ -0,0 +1,193 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 12 Feb 2018 23:59:26 +0000
+Subject: x86: Make x32 syscall support conditional on a kernel parameter
+Bug-Debian: https://bugs.debian.org/708070
+Forwarded: https://lore.kernel.org/lkml/1415245982.3398.53.camel@decadent.org.uk/T/#u
+
+Enabling x32 in the standard amd64 kernel would increase its attack
+surface while provide no benefit to the vast majority of its users.
+No-one seems interested in regularly checking for vulnerabilities
+specific to x32 (at least no-one with a white hat).
+
+Still, adding another flavour just to turn on x32 seems wasteful. And
+the only differences on syscall entry are a few instructions that mask
+out the x32 flag and compare the syscall number.
+
+Use a static key to control whether x32 syscalls are really enabled, a
+Kconfig parameter to set its default value and a kernel parameter
+"syscall.x32" to change it at boot time.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ .../admin-guide/kernel-parameters.txt | 4 ++
+ arch/x86/Kconfig | 8 ++++
+ arch/x86/entry/common.c | 3 +-
+ arch/x86/entry/syscall_64.c | 46 +++++++++++++++++++
+ arch/x86/include/asm/elf.h | 6 ++-
+ arch/x86/include/asm/syscall.h | 13 ++++++
+ 6 files changed, 78 insertions(+), 2 deletions(-)
+
+Index: debian-kernel/Documentation/admin-guide/kernel-parameters.txt
+===================================================================
+--- debian-kernel.orig/Documentation/admin-guide/kernel-parameters.txt
++++ debian-kernel/Documentation/admin-guide/kernel-parameters.txt
+@@ -5000,6 +5000,10 @@
+ later by a loaded module cannot be set this way.
+ Example: sysctl.vm.swappiness=40
+
++ syscall.x32= [KNL,x86_64] Enable/disable use of x32 syscalls on
++ an x86_64 kernel where CONFIG_X86_X32 is enabled.
++ Default depends on CONFIG_X86_X32_DISABLED.
++
+ sysfs.deprecated=0|1 [KNL]
+ Enable/disable old style sysfs layout for old udev
+ on older distributions. When this option is enabled
+Index: debian-kernel/arch/x86/Kconfig
+===================================================================
+--- debian-kernel.orig/arch/x86/Kconfig
++++ debian-kernel/arch/x86/Kconfig
+@@ -2888,6 +2888,14 @@ config COMPAT_32
+ select HAVE_UID16
+ select OLD_SIGSUSPEND3
+
++config X86_X32_DISABLED
++ bool "x32 ABI disabled by default"
++ depends on X86_X32
++ default n
++ help
++ Disable the x32 ABI unless explicitly enabled using the
++ kernel paramter "syscall.x32=y".
++
+ config COMPAT
+ def_bool y
+ depends on IA32_EMULATION || X86_X32
+Index: debian-kernel/arch/x86/entry/common.c
+===================================================================
+--- debian-kernel.orig/arch/x86/entry/common.c
++++ debian-kernel/arch/x86/entry/common.c
+@@ -383,7 +383,8 @@ __visible noinstr void do_syscall_64(uns
+ nr = array_index_nospec(nr, NR_syscalls);
+ regs->ax = sys_call_table[nr](regs);
+ #ifdef CONFIG_X86_X32_ABI
+- } else if (likely((nr & __X32_SYSCALL_BIT) &&
++ } else if (x32_enabled &&
++ likely((nr & __X32_SYSCALL_BIT) &&
+ (nr & ~__X32_SYSCALL_BIT) < X32_NR_syscalls)) {
+ nr = array_index_nospec(nr & ~__X32_SYSCALL_BIT,
+ X32_NR_syscalls);
+Index: debian-kernel/arch/x86/entry/syscall_x32.c
+===================================================================
+--- debian-kernel.orig/arch/x86/entry/syscall_x32.c
++++ debian-kernel/arch/x86/entry/syscall_x32.c
+@@ -4,6 +4,9 @@
+ #include <linux/linkage.h>
+ #include <linux/sys.h>
+ #include <linux/cache.h>
++#include <linux/moduleparam.h>
++#undef MODULE_PARAM_PREFIX
++#define MODULE_PARAM_PREFIX "syscall."
+ #include <linux/syscalls.h>
+ #include <asm/unistd.h>
+ #include <asm/syscall.h>
+@@ -27,3 +30,46 @@ asmlinkage const sys_call_ptr_t x32_sys_
+ [0 ... __NR_x32_syscall_max] = &__x64_sys_ni_syscall,
+ #include <asm/syscalls_64.h>
+ };
++
++/* Maybe enable x32 syscalls */
++
++#if defined(CONFIG_X86_X32_DISABLED)
++DEFINE_STATIC_KEY_FALSE(x32_enabled_skey);
++#else
++DEFINE_STATIC_KEY_TRUE(x32_enabled_skey);
++#endif
++
++static int __init x32_param_set(const char *val, const struct kernel_param *p)
++{
++ bool enabled;
++ int ret;
++
++ ret = kstrtobool(val, &enabled);
++ if (ret)
++ return ret;
++ if (IS_ENABLED(CONFIG_X86_X32_DISABLED)) {
++ if (enabled) {
++ static_key_enable(&x32_enabled_skey.key);
++ pr_info("Enabled x32 syscalls\n");
++ }
++ } else {
++ if (!enabled) {
++ static_key_disable(&x32_enabled_skey.key);
++ pr_info("Disabled x32 syscalls\n");
++ }
++ }
++ return 0;
++}
++
++static int x32_param_get(char *buffer, const struct kernel_param *p)
++{
++ return sprintf(buffer, "%c\n",
++ static_key_enabled(&x32_enabled_skey) ? 'Y' : 'N');
++}
++
++static const struct kernel_param_ops x32_param_ops = {
++ .set = x32_param_set,
++ .get = x32_param_get,
++};
++
++arch_param_cb(x32, &x32_param_ops, NULL, 0444);
+Index: debian-kernel/arch/x86/include/asm/elf.h
+===================================================================
+--- debian-kernel.orig/arch/x86/include/asm/elf.h
++++ debian-kernel/arch/x86/include/asm/elf.h
+@@ -11,6 +11,9 @@
+ #include <asm/user.h>
+ #include <asm/auxvec.h>
+ #include <asm/fsgsbase.h>
++#ifndef COMPILE_OFFSETS /* avoid a circular dependency on asm-offsets.h */
++#include <asm/syscall.h>
++#endif
+
+ typedef unsigned long elf_greg_t;
+
+@@ -163,7 +166,8 @@ do { \
+
+ #define compat_elf_check_arch(x) \
+ (elf_check_arch_ia32(x) || \
+- (IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64))
++ (IS_ENABLED(CONFIG_X86_X32_ABI) && x32_enabled && \
++ (x)->e_machine == EM_X86_64))
+
+ #if __USER32_DS != __USER_DS
+ # error "The following code assumes __USER32_DS == __USER_DS"
+Index: debian-kernel/arch/x86/include/asm/syscall.h
+===================================================================
+--- debian-kernel.orig/arch/x86/include/asm/syscall.h
++++ debian-kernel/arch/x86/include/asm/syscall.h
+@@ -13,6 +13,7 @@
+ #include <uapi/linux/audit.h>
+ #include <linux/sched.h>
+ #include <linux/err.h>
++#include <linux/jump_label.h>
+ #include <asm/thread_info.h> /* for TS_COMPAT */
+ #include <asm/unistd.h>
+
+@@ -31,6 +32,18 @@ extern const sys_call_ptr_t ia32_sys_cal
+ extern const sys_call_ptr_t x32_sys_call_table[];
+ #endif
+
++#if defined(CONFIG_X86_X32_ABI)
++#if defined(CONFIG_X86_X32_DISABLED)
++DECLARE_STATIC_KEY_FALSE(x32_enabled_skey);
++#define x32_enabled static_branch_unlikely(&x32_enabled_skey)
++#else
++DECLARE_STATIC_KEY_TRUE(x32_enabled_skey);
++#define x32_enabled static_branch_likely(&x32_enabled_skey)
++#endif
++#else
++#define x32_enabled 0
++#endif
++
+ /*
+ * Only the low 32 bits of orig_ax are meaningful, so we return int.
+ * This importantly ignores the high bits on 64-bit, so comparisons
diff --git a/debian/patches/features/x86/x86-memtest-WARN-if-bad-RAM-found.patch b/debian/patches/features/x86/x86-memtest-WARN-if-bad-RAM-found.patch
new file mode 100644
index 000000000..7a7952003
--- /dev/null
+++ b/debian/patches/features/x86/x86-memtest-WARN-if-bad-RAM-found.patch
@@ -0,0 +1,28 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 5 Dec 2011 04:00:58 +0000
+Subject: x86: memtest: WARN if bad RAM found
+Bug-Debian: https://bugs.debian.org/613321
+Forwarded: http://thread.gmane.org/gmane.linux.kernel/1286471
+
+Since this is not a particularly thorough test, if we find any bad
+bits of RAM then there is a fair chance that there are other bad bits
+we fail to detect.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ mm/memtest.c | 2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+--- a/mm/memtest.c
++++ b/mm/memtest.c
+@@ -26,6 +26,10 @@ static u64 patterns[] __initdata = {
+
+ static void __init reserve_bad_mem(u64 pattern, phys_addr_t start_bad, phys_addr_t end_bad)
+ {
++#ifdef CONFIG_X86
++ WARN_ONCE(1, "Bad RAM detected. Use memtest86+ to perform a thorough test\n"
++ "and the memmap= parameter to reserve the bad areas.");
++#endif
+ pr_info(" %016llx bad mem addr %pa - %pa reserved\n",
+ cpu_to_be64(pattern), &start_bad, &end_bad);
+ memblock_reserve(start_bad, end_bad - start_bad);