diff options
author | Alexandre Oliva <lxoliva@fsfla.org> | 2013-01-05 18:48:45 +0000 |
---|---|---|
committer | Alexandre Oliva <lxoliva@fsfla.org> | 2013-01-05 18:48:45 +0000 |
commit | b733a20157eb03343cd0e20b3e1c119eb3a8d768 (patch) | |
tree | deda1050199a88091192f83823c4dd6343094453 /freed-ora/current/f18 | |
parent | 88569ffc3f146f903103a0ef04fd744b656494bd (diff) | |
download | linux-libre-raptor-b733a20157eb03343cd0e20b3e1c119eb3a8d768.tar.gz linux-libre-raptor-b733a20157eb03343cd0e20b3e1c119eb3a8d768.zip |
3.7.1-2.fc18.gnu
Diffstat (limited to 'freed-ora/current/f18')
61 files changed, 2927 insertions, 16944 deletions
diff --git a/freed-ora/current/f18/0001-ext4-ext4_inode_info-diet.patch b/freed-ora/current/f18/0001-ext4-ext4_inode_info-diet.patch deleted file mode 100644 index c7858ecc6..000000000 --- a/freed-ora/current/f18/0001-ext4-ext4_inode_info-diet.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 50b61634cf8d09f9ef334919b859735d381cbe39 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov <dmonakhov@openvz.org> -Date: Fri, 28 Sep 2012 23:21:09 -0400 -Subject: [PATCH 01/13] ext4: ext4_inode_info diet - -Generic inode has unused i_private pointer which may be used as cur_aio_dio -storage. - -TODO: If cur_aio_dio will be passed as an argument to get_block_t this allow - to have concurent AIO_DIO requests. - -Reviewed-by: Zheng Liu <wenqing.lz@taobao.com> -Reviewed-by: Jan Kara <jack@suse.cz> -Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> -Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> -(cherry picked from commit f45ee3a1ea438af96e4fd2c0b16d195e67ef235f) ---- - fs/ext4/ext4.h | 12 ++++++++++-- - fs/ext4/extents.c | 4 ++-- - fs/ext4/inode.c | 6 +++--- - fs/ext4/super.c | 1 - - 4 files changed, 15 insertions(+), 8 deletions(-) - -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index c3411d4..80afc8f 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -912,8 +912,6 @@ struct ext4_inode_info { - struct list_head i_completed_io_list; - spinlock_t i_completed_io_lock; - atomic_t i_ioend_count; /* Number of outstanding io_end structs */ -- /* current io_end structure for async DIO write*/ -- ext4_io_end_t *cur_aio_dio; - atomic_t i_aiodio_unwritten; /* Nr. of inflight conversions pending */ - - spinlock_t i_block_reservation_lock; -@@ -1332,6 +1330,16 @@ static inline void ext4_set_io_unwritten_flag(struct inode *inode, - } - } - -+static inline ext4_io_end_t *ext4_inode_aio(struct inode *inode) -+{ -+ return inode->i_private; -+} -+ -+static inline void ext4_inode_aio_set(struct inode *inode, ext4_io_end_t *io) -+{ -+ inode->i_private = io; -+} -+ - /* - * Inode dynamic state flags - */ -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index aabbb3f..51fbef1 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -3600,7 +3600,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, - { - int ret = 0; - int err = 0; -- ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio; -+ ext4_io_end_t *io = ext4_inode_aio(inode); - - ext_debug("ext4_ext_handle_uninitialized_extents: inode %lu, logical " - "block %llu, max_blocks %u, flags %x, allocated %u\n", -@@ -3858,7 +3858,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, - unsigned int allocated = 0, offset = 0; - unsigned int allocated_clusters = 0; - struct ext4_allocation_request ar; -- ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio; -+ ext4_io_end_t *io = ext4_inode_aio(inode); - ext4_lblk_t cluster_offset; - - ext_debug("blocks %u/%u requested for inode %lu\n", -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index dff171c..acadd2b 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -3054,7 +3054,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, - * hook to the iocb. - */ - iocb->private = NULL; -- EXT4_I(inode)->cur_aio_dio = NULL; -+ ext4_inode_aio_set(inode, NULL); - if (!is_sync_kiocb(iocb)) { - ext4_io_end_t *io_end = - ext4_init_io_end(inode, GFP_NOFS); -@@ -3071,7 +3071,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, - * is a unwritten extents needs to be converted - * when IO is completed. - */ -- EXT4_I(inode)->cur_aio_dio = iocb->private; -+ ext4_inode_aio_set(inode, io_end); - } - - if (overwrite) -@@ -3091,7 +3091,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, - NULL, - DIO_LOCKING); - if (iocb->private) -- EXT4_I(inode)->cur_aio_dio = NULL; -+ ext4_inode_aio_set(inode, NULL); - /* - * The io_end structure takes a reference to the inode, - * that structure needs to be destroyed and the -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index c6e0cb3..270e58f 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -956,7 +956,6 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) - ei->jinode = NULL; - INIT_LIST_HEAD(&ei->i_completed_io_list); - spin_lock_init(&ei->i_completed_io_lock); -- ei->cur_aio_dio = NULL; - ei->i_sync_tid = 0; - ei->i_datasync_tid = 0; - atomic_set(&ei->i_ioend_count, 0); --- -1.7.12.rc0.22.gcdd159b - diff --git a/freed-ora/current/f18/0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch b/freed-ora/current/f18/0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch deleted file mode 100644 index cfd13f386..000000000 --- a/freed-ora/current/f18/0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 027d1aa67e32c2c80851105c6d962f3db46eb476 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov <dmonakhov@openvz.org> -Date: Fri, 28 Sep 2012 23:24:52 -0400 -Subject: [PATCH 02/13] ext4: give i_aiodio_unwritten a more appropriate name - -AIO/DIO prefix is wrong because it account unwritten extents which -also may be scheduled from buffered write endio - -Reviewed-by: Jan Kara <jack@suse.cz> -Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> -Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> -(cherry picked from commit e27f41e1b789e60e7d8cc9c81fd93ca49ef31f13) ---- - fs/ext4/ext4.h | 4 ++-- - fs/ext4/file.c | 6 +++--- - fs/ext4/page-io.c | 2 +- - fs/ext4/super.c | 2 +- - 4 files changed, 7 insertions(+), 7 deletions(-) - -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index 80afc8f..28dfd9b 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -912,7 +912,7 @@ struct ext4_inode_info { - struct list_head i_completed_io_list; - spinlock_t i_completed_io_lock; - atomic_t i_ioend_count; /* Number of outstanding io_end structs */ -- atomic_t i_aiodio_unwritten; /* Nr. of inflight conversions pending */ -+ atomic_t i_unwritten; /* Nr. of inflight conversions pending */ - - spinlock_t i_block_reservation_lock; - -@@ -1326,7 +1326,7 @@ static inline void ext4_set_io_unwritten_flag(struct inode *inode, - { - if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { - io_end->flag |= EXT4_IO_END_UNWRITTEN; -- atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); -+ atomic_inc(&EXT4_I(inode)->i_unwritten); - } - } - -diff --git a/fs/ext4/file.c b/fs/ext4/file.c -index 3b0e3bd..39335bd 100644 ---- a/fs/ext4/file.c -+++ b/fs/ext4/file.c -@@ -55,11 +55,11 @@ static int ext4_release_file(struct inode *inode, struct file *filp) - return 0; - } - --static void ext4_aiodio_wait(struct inode *inode) -+static void ext4_unwritten_wait(struct inode *inode) - { - wait_queue_head_t *wq = ext4_ioend_wq(inode); - -- wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_aiodio_unwritten) == 0)); -+ wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_unwritten) == 0)); - } - - /* -@@ -116,7 +116,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, - "performance will be poor.", - inode->i_ino, current->comm); - mutex_lock(ext4_aio_mutex(inode)); -- ext4_aiodio_wait(inode); -+ ext4_unwritten_wait(inode); - } - - BUG_ON(iocb->ki_pos != pos); -diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c -index dcdeef1..de77e31 100644 ---- a/fs/ext4/page-io.c -+++ b/fs/ext4/page-io.c -@@ -113,7 +113,7 @@ int ext4_end_io_nolock(ext4_io_end_t *io) - if (io->flag & EXT4_IO_END_DIRECT) - inode_dio_done(inode); - /* Wake up anyone waiting on unwritten extent conversion */ -- if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten)) -+ if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten)) - wake_up_all(ext4_ioend_wq(io->inode)); - return ret; - } -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index 270e58f..1b6b425 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -959,7 +959,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) - ei->i_sync_tid = 0; - ei->i_datasync_tid = 0; - atomic_set(&ei->i_ioend_count, 0); -- atomic_set(&ei->i_aiodio_unwritten, 0); -+ atomic_set(&ei->i_unwritten, 0); - - return &ei->vfs_inode; - } --- -1.7.12.rc0.22.gcdd159b - diff --git a/freed-ora/current/f18/0003-ext4-fix-unwritten-counter-leakage.patch b/freed-ora/current/f18/0003-ext4-fix-unwritten-counter-leakage.patch deleted file mode 100644 index 2f1d0d813..000000000 --- a/freed-ora/current/f18/0003-ext4-fix-unwritten-counter-leakage.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 6a0e905bb7320571ed5fdd2d5efa3d642630b4f7 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov <dmonakhov@openvz.org> -Date: Fri, 28 Sep 2012 23:36:25 -0400 -Subject: [PATCH 03/13] ext4: fix unwritten counter leakage - -ext4_set_io_unwritten_flag() will increment i_unwritten counter, so -once we mark end_io with EXT4_END_IO_UNWRITTEN we have to revert it back -on error path. - - - add missed error checks to prevent counter leakage - - ext4_end_io_nolock() will clear EXT4_END_IO_UNWRITTEN flag to signal - that conversion finished. - - add BUG_ON to ext4_free_end_io() to prevent similar leakage in future. - -Visible effect of this bug is that unaligned aio_stress may deadlock - -Reviewed-by: Jan Kara <jack@suse.cz> -Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> -Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> -(cherry picked from commit 82e54229118785badffb4ef5ba4803df25fe007f) ---- - fs/ext4/extents.c | 21 ++++++++++++++------- - fs/ext4/page-io.c | 6 +++++- - 2 files changed, 19 insertions(+), 8 deletions(-) - -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 51fbef1..e04eb4f 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -3615,6 +3615,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, - if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { - ret = ext4_split_unwritten_extents(handle, inode, map, - path, flags); -+ if (ret <= 0) -+ goto out; - /* - * Flag the inode(non aio case) or end_io struct (aio case) - * that this IO needs to conversion to written when IO is -@@ -3860,6 +3862,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, - struct ext4_allocation_request ar; - ext4_io_end_t *io = ext4_inode_aio(inode); - ext4_lblk_t cluster_offset; -+ int set_unwritten = 0; - - ext_debug("blocks %u/%u requested for inode %lu\n", - map->m_lblk, map->m_len, inode->i_ino); -@@ -4082,13 +4085,8 @@ got_allocated_blocks: - * For non asycn direct IO case, flag the inode state - * that we need to perform conversion when IO is done. - */ -- if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { -- if (io) -- ext4_set_io_unwritten_flag(inode, io); -- else -- ext4_set_inode_state(inode, -- EXT4_STATE_DIO_UNWRITTEN); -- } -+ if ((flags & EXT4_GET_BLOCKS_PRE_IO)) -+ set_unwritten = 1; - if (ext4_should_dioread_nolock(inode)) - map->m_flags |= EXT4_MAP_UNINIT; - } -@@ -4100,6 +4098,15 @@ got_allocated_blocks: - if (!err) - err = ext4_ext_insert_extent(handle, inode, path, - &newex, flags); -+ -+ if (!err && set_unwritten) { -+ if (io) -+ ext4_set_io_unwritten_flag(inode, io); -+ else -+ ext4_set_inode_state(inode, -+ EXT4_STATE_DIO_UNWRITTEN); -+ } -+ - if (err && free_on_err) { - int fb_flags = flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE ? - EXT4_FREE_BLOCKS_NO_QUOT_UPDATE : 0; -diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c -index de77e31..9970022 100644 ---- a/fs/ext4/page-io.c -+++ b/fs/ext4/page-io.c -@@ -71,6 +71,8 @@ void ext4_free_io_end(ext4_io_end_t *io) - int i; - - BUG_ON(!io); -+ BUG_ON(io->flag & EXT4_IO_END_UNWRITTEN); -+ - if (io->page) - put_page(io->page); - for (i = 0; i < io->num_io_pages; i++) -@@ -94,6 +96,8 @@ int ext4_end_io_nolock(ext4_io_end_t *io) - ssize_t size = io->size; - int ret = 0; - -+ BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN)); -+ - ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," - "list->prev 0x%p\n", - io, inode->i_ino, io->list.next, io->list.prev); -@@ -106,7 +110,7 @@ int ext4_end_io_nolock(ext4_io_end_t *io) - "(inode %lu, offset %llu, size %zd, error %d)", - inode->i_ino, offset, size, ret); - } -- -+ io->flag &= ~EXT4_IO_END_UNWRITTEN; - if (io->iocb) - aio_complete(io->iocb, io->result, 0); - --- -1.7.12.rc0.22.gcdd159b - diff --git a/freed-ora/current/f18/0004-ext4-completed_io-locking-cleanup.patch b/freed-ora/current/f18/0004-ext4-completed_io-locking-cleanup.patch deleted file mode 100644 index a358a7952..000000000 --- a/freed-ora/current/f18/0004-ext4-completed_io-locking-cleanup.patch +++ /dev/null @@ -1,520 +0,0 @@ -From e23394806df0768ed2dac87484590d2f3a730d55 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov <dmonakhov@openvz.org> -Date: Sat, 29 Sep 2012 00:14:55 -0400 -Subject: [PATCH 04/13] ext4: completed_io locking cleanup - -Current unwritten extent conversion state-machine is very fuzzy. -- For unknown reason it performs conversion under i_mutex. What for? - My diagnosis: - We already protect extent tree with i_data_sem, truncate and punch_hole - should wait for DIO, so the only data we have to protect is end_io->flags - modification, but only flush_completed_IO and end_io_work modified this - flags and we can serialize them via i_completed_io_lock. - - Currently all these games with mutex_trylock result in the following deadlock - truncate: kworker: - ext4_setattr ext4_end_io_work - mutex_lock(i_mutex) - inode_dio_wait(inode) ->BLOCK - DEADLOCK<- mutex_trylock() - inode_dio_done() - #TEST_CASE1_BEGIN - MNT=/mnt_scrach - unlink $MNT/file - fallocate -l $((1024*1024*1024)) $MNT/file - aio-stress -I 100000 -O -s 100m -n -t 1 -c 10 -o 2 -o 3 $MNT/file - sleep 2 - truncate -s 0 $MNT/file - #TEST_CASE1_END - -Or use 286's xfstests https://github.com/dmonakhov/xfstests/blob/devel/286 - -This patch makes state machine simple and clean: - -(1) xxx_end_io schedule final extent conversion simply by calling - ext4_add_complete_io(), which append it to ei->i_completed_io_list - NOTE1: because of (2A) work should be queued only if - ->i_completed_io_list was empty, otherwise the work is scheduled already. - -(2) ext4_flush_completed_IO is responsible for handling all pending - end_io from ei->i_completed_io_list - Flushing sequence consists of following stages: - A) LOCKED: Atomically drain completed_io_list to local_list - B) Perform extents conversion - C) LOCKED: move converted io's to to_free list for final deletion - This logic depends on context which we was called from. - D) Final end_io context destruction - NOTE1: i_mutex is no longer required because end_io->flags modification - is protected by ei->ext4_complete_io_lock - -Full list of changes: -- Move all completion end_io related routines to page-io.c in order to improve - logic locality -- Move open coded logic from various xx_end_xx routines to ext4_add_complete_io() -- remove EXT4_IO_END_FSYNC -- Improve SMP scalability by removing useless i_mutex which does not - protect io->flags anymore. -- Reduce lock contention on i_completed_io_lock by optimizing list walk. -- Rename ext4_end_io_nolock to end4_end_io and make it static -- Check flush completion status to ext4_ext_punch_hole(). Because it is - not good idea to punch blocks from corrupted inode. - -Changes since V3 (in request to Jan's comments): - Fall back to active flush_completed_IO() approach in order to prevent - performance issues with nolocked DIO reads. -Changes since V2: - Fix use-after-free caused by race truncate vs end_io_work - -Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> -Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> -(cherry picked from commit 28a535f9a0df060569dcc786e5bc2e1de43d7dc7) ---- - fs/ext4/ext4.h | 3 +- - fs/ext4/extents.c | 4 +- - fs/ext4/fsync.c | 81 ------------------------- - fs/ext4/indirect.c | 6 +- - fs/ext4/inode.c | 25 +------- - fs/ext4/page-io.c | 171 +++++++++++++++++++++++++++++++++++------------------ - 6 files changed, 121 insertions(+), 169 deletions(-) - -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index 28dfd9b..7687d15 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -186,7 +186,6 @@ struct mpage_da_data { - #define EXT4_IO_END_ERROR 0x0002 - #define EXT4_IO_END_QUEUED 0x0004 - #define EXT4_IO_END_DIRECT 0x0008 --#define EXT4_IO_END_IN_FSYNC 0x0010 - - struct ext4_io_page { - struct page *p_page; -@@ -2408,11 +2407,11 @@ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp, - - /* page-io.c */ - extern int __init ext4_init_pageio(void); -+extern void ext4_add_complete_io(ext4_io_end_t *io_end); - extern void ext4_exit_pageio(void); - extern void ext4_ioend_wait(struct inode *); - extern void ext4_free_io_end(ext4_io_end_t *io); - extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags); --extern int ext4_end_io_nolock(ext4_io_end_t *io); - extern void ext4_io_submit(struct ext4_io_submit *io); - extern int ext4_bio_write_page(struct ext4_io_submit *io, - struct page *page, -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index e04eb4f..1fbf2ff 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4815,7 +4815,9 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) - } - - /* finish any pending end_io work */ -- ext4_flush_completed_IO(inode); -+ err = ext4_flush_completed_IO(inode); -+ if (err) -+ return err; - - credits = ext4_writepage_trans_blocks(inode); - handle = ext4_journal_start(inode, credits); -diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c -index 2a1dcea..520b058 100644 ---- a/fs/ext4/fsync.c -+++ b/fs/ext4/fsync.c -@@ -34,87 +34,6 @@ - - #include <trace/events/ext4.h> - --static void dump_completed_IO(struct inode * inode) --{ --#ifdef EXT4FS_DEBUG -- struct list_head *cur, *before, *after; -- ext4_io_end_t *io, *io0, *io1; -- unsigned long flags; -- -- if (list_empty(&EXT4_I(inode)->i_completed_io_list)){ -- ext4_debug("inode %lu completed_io list is empty\n", inode->i_ino); -- return; -- } -- -- ext4_debug("Dump inode %lu completed_io list \n", inode->i_ino); -- spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); -- list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list){ -- cur = &io->list; -- before = cur->prev; -- io0 = container_of(before, ext4_io_end_t, list); -- after = cur->next; -- io1 = container_of(after, ext4_io_end_t, list); -- -- ext4_debug("io 0x%p from inode %lu,prev 0x%p,next 0x%p\n", -- io, inode->i_ino, io0, io1); -- } -- spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags); --#endif --} -- --/* -- * This function is called from ext4_sync_file(). -- * -- * When IO is completed, the work to convert unwritten extents to -- * written is queued on workqueue but may not get immediately -- * scheduled. When fsync is called, we need to ensure the -- * conversion is complete before fsync returns. -- * The inode keeps track of a list of pending/completed IO that -- * might needs to do the conversion. This function walks through -- * the list and convert the related unwritten extents for completed IO -- * to written. -- * The function return the number of pending IOs on success. -- */ --int ext4_flush_completed_IO(struct inode *inode) --{ -- ext4_io_end_t *io; -- struct ext4_inode_info *ei = EXT4_I(inode); -- unsigned long flags; -- int ret = 0; -- int ret2 = 0; -- -- dump_completed_IO(inode); -- spin_lock_irqsave(&ei->i_completed_io_lock, flags); -- while (!list_empty(&ei->i_completed_io_list)){ -- io = list_entry(ei->i_completed_io_list.next, -- ext4_io_end_t, list); -- list_del_init(&io->list); -- io->flag |= EXT4_IO_END_IN_FSYNC; -- /* -- * Calling ext4_end_io_nolock() to convert completed -- * IO to written. -- * -- * When ext4_sync_file() is called, run_queue() may already -- * about to flush the work corresponding to this io structure. -- * It will be upset if it founds the io structure related -- * to the work-to-be schedule is freed. -- * -- * Thus we need to keep the io structure still valid here after -- * conversion finished. The io structure has a flag to -- * avoid double converting from both fsync and background work -- * queue work. -- */ -- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -- ret = ext4_end_io_nolock(io); -- if (ret < 0) -- ret2 = ret; -- spin_lock_irqsave(&ei->i_completed_io_lock, flags); -- io->flag &= ~EXT4_IO_END_IN_FSYNC; -- } -- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -- return (ret2 < 0) ? ret2 : 0; --} -- - /* - * If we're not journaling and this is a just-created file, we have to - * sync our parent directory (if it was freshly created) since -diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c -index 830e1b2..61f13e5 100644 ---- a/fs/ext4/indirect.c -+++ b/fs/ext4/indirect.c -@@ -807,11 +807,9 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, - - retry: - if (rw == READ && ext4_should_dioread_nolock(inode)) { -- if (unlikely(!list_empty(&ei->i_completed_io_list))) { -- mutex_lock(&inode->i_mutex); -+ if (unlikely(!list_empty(&ei->i_completed_io_list))) - ext4_flush_completed_IO(inode); -- mutex_unlock(&inode->i_mutex); -- } -+ - ret = __blockdev_direct_IO(rw, iocb, inode, - inode->i_sb->s_bdev, iov, - offset, nr_segs, -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index acadd2b..dd3fd23 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -2879,9 +2879,6 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, - { - struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; - ext4_io_end_t *io_end = iocb->private; -- struct workqueue_struct *wq; -- unsigned long flags; -- struct ext4_inode_info *ei; - - /* if not async direct IO or dio with 0 bytes write, just return */ - if (!io_end || !size) -@@ -2910,24 +2907,14 @@ out: - io_end->iocb = iocb; - io_end->result = ret; - } -- wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; -- -- /* Add the io_end to per-inode completed aio dio list*/ -- ei = EXT4_I(io_end->inode); -- spin_lock_irqsave(&ei->i_completed_io_lock, flags); -- list_add_tail(&io_end->list, &ei->i_completed_io_list); -- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); - -- /* queue the work to convert unwritten extents to written */ -- queue_work(wq, &io_end->work); -+ ext4_add_complete_io(io_end); - } - - static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) - { - ext4_io_end_t *io_end = bh->b_private; -- struct workqueue_struct *wq; - struct inode *inode; -- unsigned long flags; - - if (!test_clear_buffer_uninit(bh) || !io_end) - goto out; -@@ -2946,15 +2933,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) - */ - inode = io_end->inode; - ext4_set_io_unwritten_flag(inode, io_end); -- -- /* Add the io_end to per-inode completed io list*/ -- spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); -- list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list); -- spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags); -- -- wq = EXT4_SB(inode->i_sb)->dio_unwritten_wq; -- /* queue the work to convert unwritten extents to written */ -- queue_work(wq, &io_end->work); -+ ext4_add_complete_io(io_end); - out: - bh->b_private = NULL; - bh->b_end_io = NULL; -diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c -index 9970022..5b24c40 100644 ---- a/fs/ext4/page-io.c -+++ b/fs/ext4/page-io.c -@@ -71,6 +71,7 @@ void ext4_free_io_end(ext4_io_end_t *io) - int i; - - BUG_ON(!io); -+ BUG_ON(!list_empty(&io->list)); - BUG_ON(io->flag & EXT4_IO_END_UNWRITTEN); - - if (io->page) -@@ -83,21 +84,14 @@ void ext4_free_io_end(ext4_io_end_t *io) - kmem_cache_free(io_end_cachep, io); - } - --/* -- * check a range of space and convert unwritten extents to written. -- * -- * Called with inode->i_mutex; we depend on this when we manipulate -- * io->flag, since we could otherwise race with ext4_flush_completed_IO() -- */ --int ext4_end_io_nolock(ext4_io_end_t *io) -+/* check a range of space and convert unwritten extents to written. */ -+static int ext4_end_io(ext4_io_end_t *io) - { - struct inode *inode = io->inode; - loff_t offset = io->offset; - ssize_t size = io->size; - int ret = 0; - -- BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN)); -- - ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," - "list->prev 0x%p\n", - io, inode->i_ino, io->list.next, io->list.prev); -@@ -110,7 +104,6 @@ int ext4_end_io_nolock(ext4_io_end_t *io) - "(inode %lu, offset %llu, size %zd, error %d)", - inode->i_ino, offset, size, ret); - } -- io->flag &= ~EXT4_IO_END_UNWRITTEN; - if (io->iocb) - aio_complete(io->iocb, io->result, 0); - -@@ -122,51 +115,122 @@ int ext4_end_io_nolock(ext4_io_end_t *io) - return ret; - } - --/* -- * work on completed aio dio IO, to convert unwritten extents to extents -- */ --static void ext4_end_io_work(struct work_struct *work) -+static void dump_completed_IO(struct inode *inode) -+{ -+#ifdef EXT4FS_DEBUG -+ struct list_head *cur, *before, *after; -+ ext4_io_end_t *io, *io0, *io1; -+ unsigned long flags; -+ -+ if (list_empty(&EXT4_I(inode)->i_completed_io_list)) { -+ ext4_debug("inode %lu completed_io list is empty\n", -+ inode->i_ino); -+ return; -+ } -+ -+ ext4_debug("Dump inode %lu completed_io list\n", inode->i_ino); -+ list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list) { -+ cur = &io->list; -+ before = cur->prev; -+ io0 = container_of(before, ext4_io_end_t, list); -+ after = cur->next; -+ io1 = container_of(after, ext4_io_end_t, list); -+ -+ ext4_debug("io 0x%p from inode %lu,prev 0x%p,next 0x%p\n", -+ io, inode->i_ino, io0, io1); -+ } -+#endif -+} -+ -+/* Add the io_end to per-inode completed end_io list. */ -+void ext4_add_complete_io(ext4_io_end_t *io_end) - { -- ext4_io_end_t *io = container_of(work, ext4_io_end_t, work); -- struct inode *inode = io->inode; -- struct ext4_inode_info *ei = EXT4_I(inode); -- unsigned long flags; -+ struct ext4_inode_info *ei = EXT4_I(io_end->inode); -+ struct workqueue_struct *wq; -+ unsigned long flags; -+ -+ BUG_ON(!(io_end->flag & EXT4_IO_END_UNWRITTEN)); -+ wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; - - spin_lock_irqsave(&ei->i_completed_io_lock, flags); -- if (io->flag & EXT4_IO_END_IN_FSYNC) -- goto requeue; -- if (list_empty(&io->list)) { -- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -- goto free; -+ if (list_empty(&ei->i_completed_io_list)) { -+ io_end->flag |= EXT4_IO_END_QUEUED; -+ queue_work(wq, &io_end->work); - } -+ list_add_tail(&io_end->list, &ei->i_completed_io_list); -+ spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -+} - -- if (!mutex_trylock(&inode->i_mutex)) { -- bool was_queued; --requeue: -- was_queued = !!(io->flag & EXT4_IO_END_QUEUED); -- io->flag |= EXT4_IO_END_QUEUED; -- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -- /* -- * Requeue the work instead of waiting so that the work -- * items queued after this can be processed. -- */ -- queue_work(EXT4_SB(inode->i_sb)->dio_unwritten_wq, &io->work); -- /* -- * To prevent the ext4-dio-unwritten thread from keeping -- * requeueing end_io requests and occupying cpu for too long, -- * yield the cpu if it sees an end_io request that has already -- * been requeued. -- */ -- if (was_queued) -- yield(); -- return; -+static int ext4_do_flush_completed_IO(struct inode *inode, -+ ext4_io_end_t *work_io) -+{ -+ ext4_io_end_t *io; -+ struct list_head unwritten, complete, to_free; -+ unsigned long flags; -+ struct ext4_inode_info *ei = EXT4_I(inode); -+ int err, ret = 0; -+ -+ INIT_LIST_HEAD(&complete); -+ INIT_LIST_HEAD(&to_free); -+ -+ spin_lock_irqsave(&ei->i_completed_io_lock, flags); -+ dump_completed_IO(inode); -+ list_replace_init(&ei->i_completed_io_list, &unwritten); -+ spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -+ -+ while (!list_empty(&unwritten)) { -+ io = list_entry(unwritten.next, ext4_io_end_t, list); -+ BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN)); -+ list_del_init(&io->list); -+ -+ err = ext4_end_io(io); -+ if (unlikely(!ret && err)) -+ ret = err; -+ -+ list_add_tail(&io->list, &complete); -+ } -+ /* It is important to update all flags for all end_io in one shot w/o -+ * dropping the lock.*/ -+ spin_lock_irqsave(&ei->i_completed_io_lock, flags); -+ while (!list_empty(&complete)) { -+ io = list_entry(complete.next, ext4_io_end_t, list); -+ io->flag &= ~EXT4_IO_END_UNWRITTEN; -+ /* end_io context can not be destroyed now because it still -+ * used by queued worker. Worker thread will destroy it later */ -+ if (io->flag & EXT4_IO_END_QUEUED) -+ list_del_init(&io->list); -+ else -+ list_move(&io->list, &to_free); -+ } -+ /* If we are called from worker context, it is time to clear queued -+ * flag, and destroy it's end_io if it was converted already */ -+ if (work_io) { -+ work_io->flag &= ~EXT4_IO_END_QUEUED; -+ if (!(work_io->flag & EXT4_IO_END_UNWRITTEN)) -+ list_add_tail(&work_io->list, &to_free); - } -- list_del_init(&io->list); - spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -- (void) ext4_end_io_nolock(io); -- mutex_unlock(&inode->i_mutex); --free: -- ext4_free_io_end(io); -+ -+ while (!list_empty(&to_free)) { -+ io = list_entry(to_free.next, ext4_io_end_t, list); -+ list_del_init(&io->list); -+ ext4_free_io_end(io); -+ } -+ return ret; -+} -+ -+/* -+ * work on completed aio dio IO, to convert unwritten extents to extents -+ */ -+static void ext4_end_io_work(struct work_struct *work) -+{ -+ ext4_io_end_t *io = container_of(work, ext4_io_end_t, work); -+ ext4_do_flush_completed_IO(io->inode, io); -+} -+ -+int ext4_flush_completed_IO(struct inode *inode) -+{ -+ return ext4_do_flush_completed_IO(inode, NULL); - } - - ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) -@@ -199,9 +263,7 @@ static void buffer_io_error(struct buffer_head *bh) - static void ext4_end_bio(struct bio *bio, int error) - { - ext4_io_end_t *io_end = bio->bi_private; -- struct workqueue_struct *wq; - struct inode *inode; -- unsigned long flags; - int i; - sector_t bi_sector = bio->bi_sector; - -@@ -259,14 +321,7 @@ static void ext4_end_bio(struct bio *bio, int error) - return; - } - -- /* Add the io_end to per-inode completed io list*/ -- spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); -- list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list); -- spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags); -- -- wq = EXT4_SB(inode->i_sb)->dio_unwritten_wq; -- /* queue the work to convert unwritten extents to written */ -- queue_work(wq, &io_end->work); -+ ext4_add_complete_io(io_end); - } - - void ext4_io_submit(struct ext4_io_submit *io) --- -1.7.12.rc0.22.gcdd159b - diff --git a/freed-ora/current/f18/0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch b/freed-ora/current/f18/0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch deleted file mode 100644 index cf53b8dab..000000000 --- a/freed-ora/current/f18/0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 994f567b2e99c82913a279ff438269c771b68a4b Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov <dmonakhov@openvz.org> -Date: Sat, 29 Sep 2012 00:41:21 -0400 -Subject: [PATCH 05/13] ext4: serialize dio nonlocked reads with defrag - workers - -Inode's block defrag and ext4_change_inode_journal_flag() may -affect nonlocked DIO reads result, so proper synchronization -required. - -- Add missed inode_dio_wait() calls where appropriate -- Check inode state under extra i_dio_count reference. - -Reviewed-by: Jan Kara <jack@suse.cz> -Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> -Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> -(cherry picked from commit 17335dcc471199717839b2fa3492ca36f70f1168) - -Conflicts: - fs/ext4/move_extent.c ---- - fs/ext4/ext4.h | 17 +++++++++++++++++ - fs/ext4/indirect.c | 14 ++++++++++++++ - fs/ext4/inode.c | 5 +++++ - fs/ext4/move_extent.c | 8 ++++++++ - 4 files changed, 44 insertions(+) - -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index 7687d15..3e740e9 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -1352,6 +1352,8 @@ enum { - EXT4_STATE_DIO_UNWRITTEN, /* need convert on dio done*/ - EXT4_STATE_NEWENTRY, /* File just added to dir */ - EXT4_STATE_DELALLOC_RESERVED, /* blks already reserved for delalloc */ -+ EXT4_STATE_DIOREAD_LOCK, /* Disable support for dio read -+ nolocking */ - }; - - #define EXT4_INODE_BIT_FNS(name, field, offset) \ -@@ -2459,6 +2461,21 @@ static inline void set_bitmap_uptodate(struct buffer_head *bh) - set_bit(BH_BITMAP_UPTODATE, &(bh)->b_state); - } - -+/* -+ * Disable DIO read nolock optimization, so new dioreaders will be forced -+ * to grab i_mutex -+ */ -+static inline void ext4_inode_block_unlocked_dio(struct inode *inode) -+{ -+ ext4_set_inode_state(inode, EXT4_STATE_DIOREAD_LOCK); -+ smp_mb(); -+} -+static inline void ext4_inode_resume_unlocked_dio(struct inode *inode) -+{ -+ smp_mb(); -+ ext4_clear_inode_state(inode, EXT4_STATE_DIOREAD_LOCK); -+} -+ - #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) - - /* For ioend & aio unwritten conversion wait queues */ -diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c -index 61f13e5..8d849da 100644 ---- a/fs/ext4/indirect.c -+++ b/fs/ext4/indirect.c -@@ -810,11 +810,25 @@ retry: - if (unlikely(!list_empty(&ei->i_completed_io_list))) - ext4_flush_completed_IO(inode); - -+ /* -+ * Nolock dioread optimization may be dynamically disabled -+ * via ext4_inode_block_unlocked_dio(). Check inode's state -+ * while holding extra i_dio_count ref. -+ */ -+ atomic_inc(&inode->i_dio_count); -+ smp_mb(); -+ if (unlikely(ext4_test_inode_state(inode, -+ EXT4_STATE_DIOREAD_LOCK))) { -+ inode_dio_done(inode); -+ goto locked; -+ } - ret = __blockdev_direct_IO(rw, iocb, inode, - inode->i_sb->s_bdev, iov, - offset, nr_segs, - ext4_get_block, NULL, NULL, 0); -+ inode_dio_done(inode); - } else { -+locked: - ret = blockdev_direct_IO(rw, iocb, inode, iov, - offset, nr_segs, ext4_get_block); - -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index dd3fd23..2bd7526 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -4706,6 +4706,10 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) - return err; - } - -+ /* Wait for all existing dio workers */ -+ ext4_inode_block_unlocked_dio(inode); -+ inode_dio_wait(inode); -+ - jbd2_journal_lock_updates(journal); - - /* -@@ -4725,6 +4729,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) - ext4_set_aops(inode); - - jbd2_journal_unlock_updates(journal); -+ ext4_inode_resume_unlocked_dio(inode); - - /* Finally we can mark the inode as dirty. */ - -diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c -index c5826c6..fd1e32e 100644 ---- a/fs/ext4/move_extent.c -+++ b/fs/ext4/move_extent.c -@@ -1214,6 +1214,12 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, - /* Protect orig and donor inodes against a truncate */ - mext_inode_double_lock(orig_inode, donor_inode); - -+ /* Wait for all existing dio workers */ -+ ext4_inode_block_unlocked_dio(orig_inode); -+ ext4_inode_block_unlocked_dio(donor_inode); -+ inode_dio_wait(orig_inode); -+ inode_dio_wait(donor_inode); -+ - /* Protect extent tree against block allocations via delalloc */ - double_down_write_data_sem(orig_inode, donor_inode); - /* Check the filesystem environment whether move_extent can be done */ -@@ -1413,6 +1419,8 @@ out: - kfree(holecheck_path); - } - double_up_write_data_sem(orig_inode, donor_inode); -+ ext4_inode_resume_unlocked_dio(orig_inode); -+ ext4_inode_resume_unlocked_dio(donor_inode); - mext_inode_double_unlock(orig_inode, donor_inode); - - return ret; --- -1.7.12.rc0.22.gcdd159b - diff --git a/freed-ora/current/f18/0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch b/freed-ora/current/f18/0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch deleted file mode 100644 index bddcc6024..000000000 --- a/freed-ora/current/f18/0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 4c4679fc02744ec3955e88faf5e8b6844fa8cbd3 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov <dmonakhov@openvz.org> -Date: Sat, 29 Sep 2012 00:55:23 -0400 -Subject: [PATCH 06/13] ext4: serialize unlocked dio reads with truncate - -Current serialization will works only for DIO which holds -i_mutex, but nonlocked DIO following race is possible: - -dio_nolock_read_task truncate_task - ->ext4_setattr() - ->inode_dio_wait() -->ext4_ext_direct_IO - ->ext4_ind_direct_IO - ->__blockdev_direct_IO - ->ext4_get_block - ->truncate_setsize() - ->ext4_truncate() - #alloc truncated blocks - #to other inode - ->submit_io() - #INFORMATION LEAK - -In order to serialize with unlocked DIO reads we have to -rearrange wait sequence -1) update i_size first -2) if i_size about to be reduced wait for outstanding DIO requests -3) and only after that truncate inode blocks - -Reviewed-by: Jan Kara <jack@suse.cz> -Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> -Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> -(cherry picked from commit 1c9114f9c0f10f58dd7e568a7152025af47b27e5) ---- - fs/ext4/inode.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index 2bd7526..b84322d 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -4277,7 +4277,6 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) - } - - if (attr->ia_valid & ATTR_SIZE) { -- inode_dio_wait(inode); - - if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { - struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); -@@ -4326,8 +4325,12 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) - } - - if (attr->ia_valid & ATTR_SIZE) { -- if (attr->ia_size != i_size_read(inode)) -+ if (attr->ia_size != i_size_read(inode)) { - truncate_setsize(inode, attr->ia_size); -+ /* Inode size will be reduced, wait for dio in flight */ -+ if (orphan) -+ inode_dio_wait(inode); -+ } - ext4_truncate(inode); - } - --- -1.7.12.rc0.22.gcdd159b - diff --git a/freed-ora/current/f18/0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch b/freed-ora/current/f18/0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch deleted file mode 100644 index 768215f48..000000000 --- a/freed-ora/current/f18/0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch +++ /dev/null @@ -1,41 +0,0 @@ -From ab7b8a329e12369d58e5fa59ba2e2c90370f12ef Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov <dmonakhov@openvz.org> -Date: Sat, 29 Sep 2012 00:56:15 -0400 -Subject: [PATCH 07/13] ext4: endless truncate due to nonlocked dio readers - -If we have enough aggressive DIO readers, truncate and other dio -waiters will wait forever inside inode_dio_wait(). It is reasonable -to disable nonlock DIO read optimization during truncate. - -Reviewed-by: Jan Kara <jack@suse.cz> -Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> -Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> -(cherry picked from commit 1b65007e9870e0021397b548e8cd6bbc584f9152) ---- - fs/ext4/inode.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index b84322d..3b03dd6 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -4327,9 +4327,14 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) - if (attr->ia_valid & ATTR_SIZE) { - if (attr->ia_size != i_size_read(inode)) { - truncate_setsize(inode, attr->ia_size); -- /* Inode size will be reduced, wait for dio in flight */ -- if (orphan) -+ /* Inode size will be reduced, wait for dio in flight. -+ * Temporarily disable dioread_nolock to prevent -+ * livelock. */ -+ if (orphan) { -+ ext4_inode_block_unlocked_dio(inode); - inode_dio_wait(inode); -+ ext4_inode_resume_unlocked_dio(inode); -+ } - } - ext4_truncate(inode); - } --- -1.7.12.rc0.22.gcdd159b - diff --git a/freed-ora/current/f18/0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch b/freed-ora/current/f18/0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch deleted file mode 100644 index c7733ed74..000000000 --- a/freed-ora/current/f18/0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 69e4026a2d104ffcf1b935bc889f8abcbfbb29ec Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov <dmonakhov@openvz.org> -Date: Sat, 29 Sep 2012 00:58:26 -0400 -Subject: [PATCH 08/13] ext4: serialize truncate with owerwrite DIO workers - -Jan Kara have spotted interesting issue: -There are potential data corruption issue with direct IO overwrites -racing with truncate: - Like: - dio write truncate_task - ->ext4_ext_direct_IO - ->overwrite == 1 - ->down_read(&EXT4_I(inode)->i_data_sem); - ->mutex_unlock(&inode->i_mutex); - ->ext4_setattr() - ->inode_dio_wait() - ->truncate_setsize() - ->ext4_truncate() - ->down_write(&EXT4_I(inode)->i_data_sem); - ->__blockdev_direct_IO - ->ext4_get_block - ->submit_io() - ->up_read(&EXT4_I(inode)->i_data_sem); - # truncate data blocks, allocate them to - # other inode - bad stuff happens because - # dio is still in flight. - -In order to serialize with truncate dio worker should grab extra i_dio_count -reference before drop i_mutex. - -Reviewed-by: Jan Kara <jack@suse.cz> -Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> -Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> -(cherry picked from commit 1f555cfa29e8f787d675e8390f88ce517a37271a) ---- - fs/ext4/inode.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index 3b03dd6..484a327 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -3008,6 +3008,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, - overwrite = *((int *)iocb->private); - - if (overwrite) { -+ atomic_inc(&inode->i_dio_count); - down_read(&EXT4_I(inode)->i_data_sem); - mutex_unlock(&inode->i_mutex); - } -@@ -3105,6 +3106,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, - retake_lock: - /* take i_mutex locking again if we do a ovewrite dio */ - if (overwrite) { -+ inode_dio_done(inode); - up_read(&EXT4_I(inode)->i_data_sem); - mutex_lock(&inode->i_mutex); - } --- -1.7.12.rc0.22.gcdd159b - diff --git a/freed-ora/current/f18/0009-ext4-punch_hole-should-wait-for-DIO-writers.patch b/freed-ora/current/f18/0009-ext4-punch_hole-should-wait-for-DIO-writers.patch deleted file mode 100644 index 4d7636668..000000000 --- a/freed-ora/current/f18/0009-ext4-punch_hole-should-wait-for-DIO-writers.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 71a6398a4b59ddcf920dfb68872b5a771c606e3a Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov <dmonakhov@openvz.org> -Date: Sun, 30 Sep 2012 23:03:42 -0400 -Subject: [PATCH 09/13] ext4: punch_hole should wait for DIO writers - -punch_hole is the place where we have to wait for all existing writers -(writeback, aio, dio), but currently we simply flush pended end_io request -which is not sufficient. Other issue is that punch_hole performed w/o i_mutex -held which obviously result in dangerous data corruption due to -write-after-free. - -This patch performs following changes: -- Guard punch_hole with i_mutex -- Recheck inode flags under i_mutex -- Block all new dio readers in order to prevent information leak caused by - read-after-free pattern. -- punch_hole now wait for all writers in flight - NOTE: XXX write-after-free race is still possible because new dirty pages - may appear due to mmap(), and currently there is no easy way to stop - writeback while punch_hole is in progress. - -[ Fixed error return from ext4_ext_punch_hole() to make sure that we - release i_mutex before returning EPERM or ETXTBUSY -- Ted ] - -Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> -Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> -(cherry picked from commit 02d262dffcf4c74e5c4612ee736bdb94f18ed5b9) ---- - fs/ext4/extents.c | 53 ++++++++++++++++++++++++++++++++++++----------------- - 1 file changed, 36 insertions(+), 17 deletions(-) - -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 1fbf2ff..202eb4d 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4776,9 +4776,32 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) - loff_t first_page_offset, last_page_offset; - int credits, err = 0; - -+ /* -+ * Write out all dirty pages to avoid race conditions -+ * Then release them. -+ */ -+ if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { -+ err = filemap_write_and_wait_range(mapping, -+ offset, offset + length - 1); -+ -+ if (err) -+ return err; -+ } -+ -+ mutex_lock(&inode->i_mutex); -+ /* It's not possible punch hole on append only file */ -+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) { -+ err = -EPERM; -+ goto out_mutex; -+ } -+ if (IS_SWAPFILE(inode)) { -+ err = -ETXTBSY; -+ goto out_mutex; -+ } -+ - /* No need to punch hole beyond i_size */ - if (offset >= inode->i_size) -- return 0; -+ goto out_mutex; - - /* - * If the hole extends beyond i_size, set the hole -@@ -4796,33 +4819,25 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) - first_page_offset = first_page << PAGE_CACHE_SHIFT; - last_page_offset = last_page << PAGE_CACHE_SHIFT; - -- /* -- * Write out all dirty pages to avoid race conditions -- * Then release them. -- */ -- if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { -- err = filemap_write_and_wait_range(mapping, -- offset, offset + length - 1); -- -- if (err) -- return err; -- } -- - /* Now release the pages */ - if (last_page_offset > first_page_offset) { - truncate_pagecache_range(inode, first_page_offset, - last_page_offset - 1); - } - -- /* finish any pending end_io work */ -+ /* Wait all existing dio workers, newcomers will block on i_mutex */ -+ ext4_inode_block_unlocked_dio(inode); -+ inode_dio_wait(inode); - err = ext4_flush_completed_IO(inode); - if (err) -- return err; -+ goto out_dio; - - credits = ext4_writepage_trans_blocks(inode); - handle = ext4_journal_start(inode, credits); -- if (IS_ERR(handle)) -- return PTR_ERR(handle); -+ if (IS_ERR(handle)) { -+ err = PTR_ERR(handle); -+ goto out_dio; -+ } - - err = ext4_orphan_add(handle, inode); - if (err) -@@ -4916,6 +4931,10 @@ out: - inode->i_mtime = inode->i_ctime = ext4_current_time(inode); - ext4_mark_inode_dirty(handle, inode); - ext4_journal_stop(handle); -+out_dio: -+ ext4_inode_resume_unlocked_dio(inode); -+out_mutex: -+ mutex_unlock(&inode->i_mutex); - return err; - } - int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, --- -1.7.12.rc0.22.gcdd159b - diff --git a/freed-ora/current/f18/0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch b/freed-ora/current/f18/0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch deleted file mode 100644 index d161bb765..000000000 --- a/freed-ora/current/f18/0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 66d08dd92b82dabfd64853aa4edde1547fdf9ef7 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov <dmonakhov@openvz.org> -Date: Sun, 30 Sep 2012 23:03:50 -0400 -Subject: [PATCH 10/13] ext4: fix ext_remove_space for punch_hole case - -Inode is allowed to have empty leaf only if it this is blockless inode. - -Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> -Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> -(cherry picked from commit 6f2080e64487b9963f9c6ff8a252e1abce98f2d4) ---- - fs/ext4/extents.c | 16 +++++++++------- - 1 file changed, 9 insertions(+), 7 deletions(-) - -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 202eb4d..b1c92c0 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -2572,7 +2572,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, - struct ext4_ext_path *path = NULL; - ext4_fsblk_t partial_cluster = 0; - handle_t *handle; -- int i = 0, err; -+ int i = 0, err = 0; - - ext_debug("truncate since %u to %u\n", start, end); - -@@ -2604,12 +2604,16 @@ again: - return PTR_ERR(path); - } - depth = ext_depth(inode); -+ /* Leaf not may not exist only if inode has no blocks at all */ - ex = path[depth].p_ext; - if (!ex) { -- ext4_ext_drop_refs(path); -- kfree(path); -- path = NULL; -- goto cont; -+ if (depth) { -+ EXT4_ERROR_INODE(inode, -+ "path[%d].p_hdr == NULL", -+ depth); -+ err = -EIO; -+ } -+ goto out; - } - - ee_block = le32_to_cpu(ex->ee_block); -@@ -2641,8 +2645,6 @@ again: - goto out; - } - } --cont: -- - /* - * We start scanning from right side, freeing all the blocks - * after i_size and walking into the tree depth-wise. --- -1.7.12.rc0.22.gcdd159b - diff --git a/freed-ora/current/f18/0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch b/freed-ora/current/f18/0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch deleted file mode 100644 index 517b20129..000000000 --- a/freed-ora/current/f18/0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch +++ /dev/null @@ -1,176 +0,0 @@ -From ca6d3910cbf8854f3f3b9846391f669733899101 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov <dmonakhov@openvz.org> -Date: Fri, 5 Oct 2012 11:31:55 -0400 -Subject: [PATCH 11/13] ext4: fix ext4_flush_completed_IO wait semantics - -BUG #1) All places where we call ext4_flush_completed_IO are broken - because buffered io and DIO/AIO goes through three stages - 1) submitted io, - 2) completed io (in i_completed_io_list) conversion pended - 3) finished io (conversion done) - And by calling ext4_flush_completed_IO we will flush only - requests which were in (2) stage, which is wrong because: - 1) punch_hole and truncate _must_ wait for all outstanding unwritten io - regardless to it's state. - 2) fsync and nolock_dio_read should also wait because there is - a time window between end_page_writeback() and ext4_add_complete_io() - As result integrity fsync is broken in case of buffered write - to fallocated region: - fsync blkdev_completion - ->filemap_write_and_wait_range - ->ext4_end_bio - ->end_page_writeback - <-- filemap_write_and_wait_range return - ->ext4_flush_completed_IO - sees empty i_completed_io_list but pended - conversion still exist - ->ext4_add_complete_io - -BUG #2) Race window becomes wider due to the 'ext4: completed_io -locking cleanup V4' patch series - -This patch make following changes: -1) ext4_flush_completed_io() now first try to flush completed io and when - wait for any outstanding unwritten io via ext4_unwritten_wait() -2) Rename function to more appropriate name. -3) Assert that all callers of ext4_flush_unwritten_io should hold i_mutex to - prevent endless wait - -Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> -Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> -Reviewed-by: Jan Kara <jack@suse.cz> -(cherry picked from commit c278531d39f3158bfee93dc67da0b77e09776de2) ---- - fs/ext4/ext4.h | 3 ++- - fs/ext4/extents.c | 6 +++--- - fs/ext4/file.c | 2 +- - fs/ext4/fsync.c | 2 +- - fs/ext4/indirect.c | 8 +++++--- - fs/ext4/page-io.c | 11 +++++++---- - 6 files changed, 19 insertions(+), 13 deletions(-) - -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index 3e740e9..7f13292 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -1941,7 +1941,7 @@ extern void ext4_htree_free_dir_info(struct dir_private_info *p); - - /* fsync.c */ - extern int ext4_sync_file(struct file *, loff_t, loff_t, int); --extern int ext4_flush_completed_IO(struct inode *); -+extern int ext4_flush_unwritten_io(struct inode *); - - /* hash.c */ - extern int ext4fs_dirhash(const char *name, int len, struct -@@ -2361,6 +2361,7 @@ extern const struct file_operations ext4_dir_operations; - extern const struct inode_operations ext4_file_inode_operations; - extern const struct file_operations ext4_file_operations; - extern loff_t ext4_llseek(struct file *file, loff_t offset, int origin); -+extern void ext4_unwritten_wait(struct inode *inode); - - /* namei.c */ - extern const struct inode_operations ext4_dir_inode_operations; -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index b1c92c0..37f46eb 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4250,7 +4250,7 @@ void ext4_ext_truncate(struct inode *inode) - * finish any pending end_io work so we won't run the risk of - * converting any truncated blocks to initialized later - */ -- ext4_flush_completed_IO(inode); -+ ext4_flush_unwritten_io(inode); - - /* - * probably first extent we're gonna free will be last in block -@@ -4829,10 +4829,10 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) - - /* Wait all existing dio workers, newcomers will block on i_mutex */ - ext4_inode_block_unlocked_dio(inode); -- inode_dio_wait(inode); -- err = ext4_flush_completed_IO(inode); -+ err = ext4_flush_unwritten_io(inode); - if (err) - goto out_dio; -+ inode_dio_wait(inode); - - credits = ext4_writepage_trans_blocks(inode); - handle = ext4_journal_start(inode, credits); -diff --git a/fs/ext4/file.c b/fs/ext4/file.c -index 39335bd..ca6f07a 100644 ---- a/fs/ext4/file.c -+++ b/fs/ext4/file.c -@@ -55,7 +55,7 @@ static int ext4_release_file(struct inode *inode, struct file *filp) - return 0; - } - --static void ext4_unwritten_wait(struct inode *inode) -+void ext4_unwritten_wait(struct inode *inode) - { - wait_queue_head_t *wq = ext4_ioend_wq(inode); - -diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c -index 520b058..76051c6 100644 ---- a/fs/ext4/fsync.c -+++ b/fs/ext4/fsync.c -@@ -138,7 +138,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) - if (inode->i_sb->s_flags & MS_RDONLY) - goto out; - -- ret = ext4_flush_completed_IO(inode); -+ ret = ext4_flush_unwritten_io(inode); - if (ret < 0) - goto out; - -diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c -index 8d849da..792e388 100644 ---- a/fs/ext4/indirect.c -+++ b/fs/ext4/indirect.c -@@ -807,9 +807,11 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, - - retry: - if (rw == READ && ext4_should_dioread_nolock(inode)) { -- if (unlikely(!list_empty(&ei->i_completed_io_list))) -- ext4_flush_completed_IO(inode); -- -+ if (unlikely(atomic_read(&EXT4_I(inode)->i_unwritten))) { -+ mutex_lock(&inode->i_mutex); -+ ext4_flush_unwritten_io(inode); -+ mutex_unlock(&inode->i_mutex); -+ } - /* - * Nolock dioread optimization may be dynamically disabled - * via ext4_inode_block_unlocked_dio(). Check inode's state -diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c -index 5b24c40..68e896e 100644 ---- a/fs/ext4/page-io.c -+++ b/fs/ext4/page-io.c -@@ -189,8 +189,6 @@ static int ext4_do_flush_completed_IO(struct inode *inode, - - list_add_tail(&io->list, &complete); - } -- /* It is important to update all flags for all end_io in one shot w/o -- * dropping the lock.*/ - spin_lock_irqsave(&ei->i_completed_io_lock, flags); - while (!list_empty(&complete)) { - io = list_entry(complete.next, ext4_io_end_t, list); -@@ -228,9 +226,14 @@ static void ext4_end_io_work(struct work_struct *work) - ext4_do_flush_completed_IO(io->inode, io); - } - --int ext4_flush_completed_IO(struct inode *inode) -+int ext4_flush_unwritten_io(struct inode *inode) - { -- return ext4_do_flush_completed_IO(inode, NULL); -+ int ret; -+ WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex) && -+ !(inode->i_state & I_FREEING)); -+ ret = ext4_do_flush_completed_IO(inode, NULL); -+ ext4_unwritten_wait(inode); -+ return ret; - } - - ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) --- -1.7.12.rc0.22.gcdd159b - diff --git a/freed-ora/current/f18/0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch b/freed-ora/current/f18/0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch deleted file mode 100644 index 3fcaef1f2..000000000 --- a/freed-ora/current/f18/0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 9f00d109efeaf4d12d56c8e46cd13af80e344f97 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov <dmonakhov@openvz.org> -Date: Fri, 5 Oct 2012 11:32:02 -0400 -Subject: [PATCH 12/13] ext4: serialize fallocate with - ext4_convert_unwritten_extents - -Fallocate should wait for pended ext4_convert_unwritten_extents() -otherwise following race may happen: - -ftruncate( ,12288); -fallocate( ,0, 4096) -io_sibmit( ,0, 4096); /* Write to fallocated area, split extent if needed */ -fallocate( ,0, 8192); /* Grow extent and broke assumption about extent */ - -Later kwork completion will do: - ->ext4_convert_unwritten_extents (0, 4096) - ->ext4_map_blocks(handle, inode, &map, EXT4_GET_BLOCKS_IO_CONVERT_EXT); - ->ext4_ext_map_blocks() /* Will find new extent: ex = [0,2] !!!!!! */ - ->ext4_ext_handle_uninitialized_extents() - ->ext4_convert_unwritten_extents_endio() - /* convert [0,2] extent to initialized, but only[0,1] was written */ - -Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> -Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> -(cherry picked from commit 60d4616f3dc63371b3dc367e5e88fd4b4f037f65) ---- - fs/ext4/extents.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 37f46eb..ea2db86 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4410,6 +4410,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) - */ - if (len <= EXT_UNINIT_MAX_LEN << blkbits) - flags |= EXT4_GET_BLOCKS_NO_NORMALIZE; -+ -+ /* Prevent race condition between unwritten */ -+ ext4_flush_unwritten_io(inode); - retry: - while (ret >= 0 && ret < max_blocks) { - map.m_lblk = map.m_lblk + ret; --- -1.7.12.rc0.22.gcdd159b - diff --git a/freed-ora/current/f18/Bluetooth-Add-support-for-BCM20702A0.patch b/freed-ora/current/f18/Bluetooth-Add-support-for-BCM20702A0.patch index 73f00fc43..99178d757 100644 --- a/freed-ora/current/f18/Bluetooth-Add-support-for-BCM20702A0.patch +++ b/freed-ora/current/f18/Bluetooth-Add-support-for-BCM20702A0.patch @@ -1,67 +1,3 @@ -From 7f198e1cc6d4fda9c84c0da4fc3aafb441342f78 Mon Sep 17 00:00:00 2001 -From: Jaroslav Resler <resler@cs.cas.cz> -Date: Tue, 11 Sep 2012 17:25:32 +0800 -Subject: [PATCH 1/2] Bluetooth: Add support for BCM20702A0 [04ca, 2003] - -Add another vendor specific ID for BCM20702A0. - -output of usb-devices: -T: Bus=01 Lev=02 Prnt=02 Port=03 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 -D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 -P: Vendor=04ca ProdID=2003 Rev= 1.12 -S: Manufacturer=Broadcom Corp -S: Product=BCM20702A0 -S: SerialNumber=446D57861623 -C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr= 0mA -I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms -E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms -E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms -I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms -E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms -I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms -E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms -I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms -E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms -I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms -E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms -I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms -E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms -I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms -E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms -I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) -E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms -E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms -I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) - -Signed-off-by: Cho, Yu-Chen <acho@suse.com> -Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> ---- - drivers/bluetooth/btusb.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c -index 654e248..b167944 100644 ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -96,6 +96,7 @@ static struct usb_device_id btusb_table[] = { - { USB_DEVICE(0x0c10, 0x0000) }, - - /* Broadcom BCM20702A0 */ -+ { USB_DEVICE(0x04ca, 0x2003) }, - { USB_DEVICE(0x0489, 0xe042) }, - { USB_DEVICE(0x413c, 0x8197) }, - --- -1.8.0 - - From a5f86c3423428c8e28b6501d0e9c3929ca91f07d Mon Sep 17 00:00:00 2001 From: Jeff Cook <jeff@deserettechnology.com> Date: Fri, 9 Nov 2012 16:39:48 -0700 diff --git a/freed-ora/current/f18/SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch b/freed-ora/current/f18/SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch deleted file mode 100644 index 0d83e8d03..000000000 --- a/freed-ora/current/f18/SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 95ab000388974d8ffef8257306b4be6e8778b768 Mon Sep 17 00:00:00 2001 -From: Jianpeng Ma <majianpeng@gmail.com> -Date: Sat, 4 Aug 2012 10:34:14 +0800 -Subject: [PATCH] [SCSI] mvsas: Fix oops when ata commond timeout. - -Kernel message follows: - -[ 511.712011] sd 11:0:0:0: [sdf] command ffff8800a4e81400 timed out -[ 511.712022] sas: Enter sas_scsi_recover_host busy: 1 failed: 1 -[ 511.712024] sas: trying to find task 0xffff8800a4d24c80 -[ 511.712026] sas: sas_scsi_find_task: aborting task 0xffff8800a4d24c80 -[ 511.712029] drivers/scsi/mvsas/mv_sas.c 1631:mvs_abort_task() -mvi=ffff8800b5300000 task=ffff8800a4d24c80 slot=ffff8800b5325038 -slot_idx=x0 -[ 511.712035] BUG: unable to handle kernel NULL pointer dereference at -0000000000000058 -[ 511.712040] IP: [<ffffffff815f8c0c>] _raw_spin_lock_irqsave+0xc/0x30 -[ 511.712047] PGD 0 -[ 511.712049] Oops: 0002 [#1] SMP -[ 511.712052] Modules linked in: mvsas libsas scsi_transport_sas -raid456 async_pq async_xor xor async_memcpy async_raid6_recov raid6_pq -async_tx [last unloaded: mvsas] -[ 511.712062] CPU 3 -[ 511.712066] Pid: 7322, comm: scsi_eh_11 Not tainted 3.5.0+ #106 To Be -Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M. -[ 511.712068] RIP: 0010:[<ffffffff815f8c0c>] [<ffffffff815f8c0c>] -_raw_spin_lock_irqsave+0xc/0x30 -[ 511.712073] RSP: 0018:ffff880098d3bcb0 EFLAGS: 00010086 -[ 511.712074] RAX: 0000000000000286 RBX: 0000000000000058 RCX: -00000000000000c3 -[ 511.712076] RDX: 0000000000000100 RSI: 0000000000000046 RDI: -0000000000000058 -[ 511.712078] RBP: ffff880098d3bcb0 R08: 000000000000000a R09: -0000000000000000 -[ 511.712080] R10: 00000000000004e8 R11: 00000000000004e7 R12: -ffff8800a4d24c80 -[ 511.712082] R13: 0000000000000050 R14: ffff8800b5325038 R15: -ffff8800a4eafe00 -[ 511.712084] FS: 0000000000000000(0000) GS:ffff8800bdb80000(0000) -knlGS:0000000000000000 -[ 511.712086] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b -[ 511.712088] CR2: 0000000000000058 CR3: 00000000a4ce6000 CR4: -00000000000407e0 -[ 511.712090] DR0: 0000000000000000 DR1: 0000000000000000 DR2: -0000000000000000 -[ 511.712091] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: -0000000000000400 -[ 511.712093] Process scsi_eh_11 (pid: 7322, threadinfo -ffff880098d3a000, task ffff8800a61dde40) -[ 511.712095] Stack: -[ 511.712096] ffff880098d3bce0 ffffffff81060683 ffff880000000000 -0000000000000000 -[ 511.712099] ffff8800a4d24c80 ffff8800b5300000 ffff880098d3bcf0 -ffffffffa0076a88 -[ 511.712102] ffff880098d3bd50 ffffffffa0079bb5 ffff880000000000 -ffff880000000018 -[ 511.712106] Call Trace: -[ 511.712110] [<ffffffff81060683>] complete+0x23/0x60 -[ 511.712115] [<ffffffffa0076a88>] mvs_tmf_timedout+0x18/0x20 [mvsas] -[ 511.712119] [<ffffffffa0079bb5>] mvs_slot_complete+0x765/0x7d0 -[mvsas] -[ 511.712125] [<ffffffffa005a17d>] sas_scsi_recover_host+0x55d/0xdb0 -[libsas] -[ 511.712128] [<ffffffff8106d600>] ? idle_balance+0xe0/0x130 -[ 511.712133] [<ffffffff813b150c>] scsi_error_handler+0xcc/0x470 -[ 511.712136] [<ffffffff815f7ad0>] ? __schedule+0x370/0x730 -[ 511.712139] [<ffffffff8105f728>] ? __wake_up_common+0x58/0x90 -[ 511.712142] [<ffffffff813b1440>] ? scsi_eh_get_sense+0x110/0x110 -[ 511.712146] [<ffffffff810571be>] kthread+0x8e/0xa0 -[ 511.712150] [<ffffffff816015f4>] kernel_thread_helper+0x4/0x10 -[ 511.712153] [<ffffffff81057130>] ? flush_kthread_work+0x120/0x120 -[ 511.712156] [<ffffffff816015f0>] ? gs_change+0xb/0xb -[ 511.712157] Code: 8a 00 01 00 00 89 d0 f0 66 0f b1 0f 66 39 d0 0f 94 -c0 0f b6 c0 5d c3 0f 1f 84 00 00 00 00 00 55 48 89 e5 9c 58 fa ba 00 01 -00 00 <f0> 66 0f c1 17 0f b6 ce 38 d1 74 11 0f 1f 84 00 00 00 00 00 f3 -[ 511.712191] RIP [<ffffffff815f8c0c>] _raw_spin_lock_irqsave+0xc/0x30 -[ 511.712194] RSP <ffff880098d3bcb0> -[ 511.712196] CR2: 0000000000000058 -[ 511.712198] ---[ end trace a781c7b1e65db92c ]--- - -Signed-off-by: Jianpeng Ma <majianpeng@gmail.com> -Signed-off-by: James Bottomley <JBottomley@Parallels.com> ---- - drivers/scsi/mvsas/mv_sas.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c -index 4539d59..a3776d6 100644 ---- a/drivers/scsi/mvsas/mv_sas.c -+++ b/drivers/scsi/mvsas/mv_sas.c -@@ -1629,7 +1629,7 @@ int mvs_abort_task(struct sas_task *task) - mv_dprintk("mvs_abort_task() mvi=%p task=%p " - "slot=%p slot_idx=x%x\n", - mvi, task, slot, slot_idx); -- mvs_tmf_timedout((unsigned long)task); -+ task->task_state_flags |= SAS_TASK_STATE_ABORTED; - mvs_slot_task_free(mvi, task, slot, slot_idx); - rc = TMF_RESP_FUNC_COMPLETE; - goto out; --- -1.8.0 - diff --git a/freed-ora/current/f18/arm-fix_radio_shark.patch b/freed-ora/current/f18/arm-fix_radio_shark.patch deleted file mode 100644 index 63296a90e..000000000 --- a/freed-ora/current/f18/arm-fix_radio_shark.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig -index ff3af6e..f99fa25 100644 ---- a/sound/pci/Kconfig -+++ b/sound/pci/Kconfig -@@ -2,8 +2,8 @@ - - config SND_TEA575X - tristate -- depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO -- default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO -+ depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK -+ default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK - - menuconfig SND_PCI - bool "PCI sound devices" diff --git a/freed-ora/current/f18/arm-highbank-sata-fix.patch b/freed-ora/current/f18/arm-highbank-sata-fix.patch deleted file mode 100644 index fda7b219e..000000000 --- a/freed-ora/current/f18/arm-highbank-sata-fix.patch +++ /dev/null @@ -1,599 +0,0 @@ -From: Mark Langsdorf <mark.langsdorf@calxeda.com> -Date: Thu, 6 Sep 2012 21:03:30 +0000 (-0500) -Subject: ata: add platform driver for Calxeda AHCI controller -X-Git-Tag: next-20121002~68^2~5 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=8996b89d6bc98ae2f6d6e6e624a42a3f89d06949;hp=100f586bd0959fe0e52b8a0b8cb49a3df1c6b044 - -ata: add platform driver for Calxeda AHCI controller - -Calxeda highbank SATA phy has intermittent problems bringing up a link -with Gen3 drives. Retrying the phy hard reset can work-around this issue, -but each reset also disables spread spectrum support. The reset function -also needs to reprogram the phy to enable spread spectrum support. - -Create a new driver based on ahci_platform to support the Calxeda Highbank -SATA controller. - -Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com> -Signed-off-by: Rob Herring <rob.herring@calxeda.com> -Signed-off-by: Jeff Garzik <jgarzik@redhat.com> ---- - -diff --git a/Documentation/devicetree/bindings/arm/calxeda/combophy.txt b/Documentation/devicetree/bindings/arm/calxeda/combophy.txt -new file mode 100644 -index 0000000..6622bdb ---- /dev/null -+++ b/Documentation/devicetree/bindings/arm/calxeda/combophy.txt -@@ -0,0 +1,17 @@ -+Calxeda Highbank Combination Phys for SATA -+ -+Properties: -+- compatible : Should be "calxeda,hb-combophy" -+- #phy-cells: Should be 1. -+- reg : Address and size for Combination Phy registers. -+- phydev: device ID for programming the combophy. -+ -+Example: -+ -+ combophy5: combo-phy@fff5d000 { -+ compatible = "calxeda,hb-combophy"; -+ #phy-cells = <1>; -+ reg = <0xfff5d000 0x1000>; -+ phydev = <31>; -+ }; -+ -diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt -index 8bb8a76..147c1f6 100644 ---- a/Documentation/devicetree/bindings/ata/ahci-platform.txt -+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt -@@ -8,9 +8,17 @@ Required properties: - - interrupts : <interrupt mapping for SATA IRQ> - - reg : <registers mapping> - -+Optional properties: -+- calxeda,port-phys: phandle-combophy and lane assignment, which maps each -+ SATA port to a combophy and a lane within that -+ combophy -+ - Example: - sata@ffe08000 { - compatible = "calxeda,hb-ahci"; - reg = <0xffe08000 0x1000>; - interrupts = <115>; -+ calxeda,port-phys = <&combophy5 0 &combophy0 0 &combophy0 1 -+ &combophy0 2 &combophy0 3>; -+ - }; -diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts -index 9fecf1a..5204cf7 100644 ---- a/arch/arm/boot/dts/highbank.dts -+++ b/arch/arm/boot/dts/highbank.dts -@@ -121,6 +121,9 @@ - compatible = "calxeda,hb-ahci"; - reg = <0xffe08000 0x10000>; - interrupts = <0 83 4>; -+ calxeda,port-phys = <&combophy5 0 &combophy0 0 -+ &combophy0 1 &combophy0 2 -+ &combophy0 3>; - }; - - sdhci@ffe0e000 { -@@ -306,5 +309,19 @@ - reg = <0xfff51000 0x1000>; - interrupts = <0 80 4 0 81 4 0 82 4>; - }; -+ -+ combophy0: combo-phy@fff58000 { -+ compatible = "calxeda,hb-combophy"; -+ #phy-cells = <1>; -+ reg = <0xfff58000 0x1000>; -+ phydev = <5>; -+ }; -+ -+ combophy5: combo-phy@fff5d000 { -+ compatible = "calxeda,hb-combophy"; -+ #phy-cells = <1>; -+ reg = <0xfff5d000 0x1000>; -+ phydev = <31>; -+ }; - }; - }; -diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig -index 27cecd3..e08d322 100644 ---- a/drivers/ata/Kconfig -+++ b/drivers/ata/Kconfig -@@ -214,6 +214,14 @@ config SATA_DWC_VDEBUG - help - This option enables the taskfile dumping and NCQ debugging. - -+config SATA_HIGHBANK -+ tristate "Calxeda Highbank SATA support" -+ help -+ This option enables support for the Calxeda Highbank SoC's -+ onboard SATA. -+ -+ If unsure, say N. -+ - config SATA_MV - tristate "Marvell SATA support" - help -diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile -index a454a13..8b384f1 100644 ---- a/drivers/ata/Makefile -+++ b/drivers/ata/Makefile -@@ -9,6 +9,7 @@ obj-$(CONFIG_SATA_FSL) += sata_fsl.o - obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o - obj-$(CONFIG_SATA_SIL24) += sata_sil24.o - obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o -+obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o - - # SFF w/ custom DMA - obj-$(CONFIG_PDC_ADMA) += pdc_adma.o -diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c -index 09728e0..dc187c7 100644 ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -277,7 +277,6 @@ static int ahci_resume(struct device *dev) - SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume); - - static const struct of_device_id ahci_of_match[] = { -- { .compatible = "calxeda,hb-ahci", }, - { .compatible = "snps,spear-ahci", }, - {}, - }; -diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c -new file mode 100644 -index 0000000..0d7c4c2 ---- /dev/null -+++ b/drivers/ata/sata_highbank.c -@@ -0,0 +1,450 @@ -+/* -+ * Calxeda Highbank AHCI SATA platform driver -+ * Copyright 2012 Calxeda, Inc. -+ * -+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program. If not, see <http://www.gnu.org/licenses/>. -+ */ -+#include <linux/kernel.h> -+#include <linux/gfp.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/types.h> -+#include <linux/err.h> -+#include <linux/io.h> -+#include <linux/spinlock.h> -+#include <linux/device.h> -+#include <linux/of_device.h> -+#include <linux/of_address.h> -+#include <linux/platform_device.h> -+#include <linux/libata.h> -+#include <linux/ahci_platform.h> -+#include <linux/interrupt.h> -+#include <linux/delay.h> -+#include <linux/export.h> -+#include "ahci.h" -+ -+#define CPHY_MAP(dev, addr) ((((dev) & 0x1f) << 7) | (((addr) >> 9) & 0x7f)) -+#define CPHY_ADDR(addr) (((addr) & 0x1ff) << 2) -+#define SERDES_CR_CTL 0x80a0 -+#define SERDES_CR_ADDR 0x80a1 -+#define SERDES_CR_DATA 0x80a2 -+#define CR_BUSY 0x0001 -+#define CR_START 0x0001 -+#define CR_WR_RDN 0x0002 -+#define CPHY_RX_INPUT_STS 0x2002 -+#define CPHY_SATA_OVERRIDE 0x4000 -+#define CPHY_OVERRIDE 0x2005 -+#define SPHY_LANE 0x100 -+#define SPHY_HALF_RATE 0x0001 -+#define CPHY_SATA_DPLL_MODE 0x0700 -+#define CPHY_SATA_DPLL_SHIFT 8 -+#define CPHY_SATA_DPLL_RESET (1 << 11) -+#define CPHY_PHY_COUNT 6 -+#define CPHY_LANE_COUNT 4 -+#define CPHY_PORT_COUNT (CPHY_PHY_COUNT * CPHY_LANE_COUNT) -+ -+static DEFINE_SPINLOCK(cphy_lock); -+/* Each of the 6 phys can have up to 4 sata ports attached to i. Map 0-based -+ * sata ports to their phys and then to their lanes within the phys -+ */ -+struct phy_lane_info { -+ void __iomem *phy_base; -+ u8 lane_mapping; -+ u8 phy_devs; -+}; -+static struct phy_lane_info port_data[CPHY_PORT_COUNT]; -+ -+static u32 __combo_phy_reg_read(u8 sata_port, u32 addr) -+{ -+ u32 data; -+ u8 dev = port_data[sata_port].phy_devs; -+ spin_lock(&cphy_lock); -+ writel(CPHY_MAP(dev, addr), port_data[sata_port].phy_base + 0x800); -+ data = readl(port_data[sata_port].phy_base + CPHY_ADDR(addr)); -+ spin_unlock(&cphy_lock); -+ return data; -+} -+ -+static void __combo_phy_reg_write(u8 sata_port, u32 addr, u32 data) -+{ -+ u8 dev = port_data[sata_port].phy_devs; -+ spin_lock(&cphy_lock); -+ writel(CPHY_MAP(dev, addr), port_data[sata_port].phy_base + 0x800); -+ writel(data, port_data[sata_port].phy_base + CPHY_ADDR(addr)); -+ spin_unlock(&cphy_lock); -+} -+ -+static void combo_phy_wait_for_ready(u8 sata_port) -+{ -+ while (__combo_phy_reg_read(sata_port, SERDES_CR_CTL) & CR_BUSY) -+ udelay(5); -+} -+ -+static u32 combo_phy_read(u8 sata_port, u32 addr) -+{ -+ combo_phy_wait_for_ready(sata_port); -+ __combo_phy_reg_write(sata_port, SERDES_CR_ADDR, addr); -+ __combo_phy_reg_write(sata_port, SERDES_CR_CTL, CR_START); -+ combo_phy_wait_for_ready(sata_port); -+ return __combo_phy_reg_read(sata_port, SERDES_CR_DATA); -+} -+ -+static void combo_phy_write(u8 sata_port, u32 addr, u32 data) -+{ -+ combo_phy_wait_for_ready(sata_port); -+ __combo_phy_reg_write(sata_port, SERDES_CR_ADDR, addr); -+ __combo_phy_reg_write(sata_port, SERDES_CR_DATA, data); -+ __combo_phy_reg_write(sata_port, SERDES_CR_CTL, CR_WR_RDN | CR_START); -+} -+ -+static void highbank_cphy_disable_overrides(u8 sata_port) -+{ -+ u8 lane = port_data[sata_port].lane_mapping; -+ u32 tmp; -+ if (unlikely(port_data[sata_port].phy_base == NULL)) -+ return; -+ tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); -+ tmp &= ~CPHY_SATA_OVERRIDE; -+ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); -+} -+ -+static void cphy_override_rx_mode(u8 sata_port, u32 val) -+{ -+ u8 lane = port_data[sata_port].lane_mapping; -+ u32 tmp; -+ tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); -+ tmp &= ~CPHY_SATA_OVERRIDE; -+ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); -+ -+ tmp |= CPHY_SATA_OVERRIDE; -+ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); -+ -+ tmp &= ~CPHY_SATA_DPLL_MODE; -+ tmp |= val << CPHY_SATA_DPLL_SHIFT; -+ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); -+ -+ tmp |= CPHY_SATA_DPLL_RESET; -+ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); -+ -+ tmp &= ~CPHY_SATA_DPLL_RESET; -+ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); -+ -+ msleep(15); -+} -+ -+static void highbank_cphy_override_lane(u8 sata_port) -+{ -+ u8 lane = port_data[sata_port].lane_mapping; -+ u32 tmp, k = 0; -+ -+ if (unlikely(port_data[sata_port].phy_base == NULL)) -+ return; -+ do { -+ tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + -+ lane * SPHY_LANE); -+ } while ((tmp & SPHY_HALF_RATE) && (k++ < 1000)); -+ cphy_override_rx_mode(sata_port, 3); -+} -+ -+static int highbank_initialize_phys(struct device *dev, void __iomem *addr) -+{ -+ struct device_node *sata_node = dev->of_node; -+ int phy_count = 0, phy, port = 0; -+ void __iomem *cphy_base[CPHY_PHY_COUNT]; -+ struct device_node *phy_nodes[CPHY_PHY_COUNT]; -+ memset(port_data, 0, sizeof(struct phy_lane_info) * CPHY_PORT_COUNT); -+ memset(phy_nodes, 0, sizeof(struct device_node*) * CPHY_PHY_COUNT); -+ -+ do { -+ u32 tmp; -+ struct of_phandle_args phy_data; -+ if (of_parse_phandle_with_args(sata_node, -+ "calxeda,port-phys", "#phy-cells", -+ port, &phy_data)) -+ break; -+ for (phy = 0; phy < phy_count; phy++) { -+ if (phy_nodes[phy] == phy_data.np) -+ break; -+ } -+ if (phy_nodes[phy] == NULL) { -+ phy_nodes[phy] = phy_data.np; -+ cphy_base[phy] = of_iomap(phy_nodes[phy], 0); -+ if (cphy_base[phy] == NULL) { -+ return 0; -+ } -+ phy_count += 1; -+ } -+ port_data[port].lane_mapping = phy_data.args[0]; -+ of_property_read_u32(phy_nodes[phy], "phydev", &tmp); -+ port_data[port].phy_devs = tmp; -+ port_data[port].phy_base = cphy_base[phy]; -+ of_node_put(phy_data.np); -+ port += 1; -+ } while (port < CPHY_PORT_COUNT); -+ return 0; -+} -+ -+static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class, -+ unsigned long deadline) -+{ -+ const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); -+ struct ata_port *ap = link->ap; -+ struct ahci_port_priv *pp = ap->private_data; -+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; -+ struct ata_taskfile tf; -+ bool online; -+ u32 sstatus; -+ int rc; -+ int retry = 10; -+ -+ ahci_stop_engine(ap); -+ -+ /* clear D2H reception area to properly wait for D2H FIS */ -+ ata_tf_init(link->device, &tf); -+ tf.command = 0x80; -+ ata_tf_to_fis(&tf, 0, 0, d2h_fis); -+ -+ do { -+ highbank_cphy_disable_overrides(link->ap->port_no); -+ rc = sata_link_hardreset(link, timing, deadline, &online, NULL); -+ highbank_cphy_override_lane(link->ap->port_no); -+ -+ /* If the status is 1, we are connected, but the link did not -+ * come up. So retry resetting the link again. -+ */ -+ if (sata_scr_read(link, SCR_STATUS, &sstatus)) -+ break; -+ if (!(sstatus & 0x3)) -+ break; -+ } while (!online && retry--); -+ -+ ahci_start_engine(ap); -+ -+ if (online) -+ *class = ahci_dev_classify(ap); -+ -+ return rc; -+} -+ -+static struct ata_port_operations ahci_highbank_ops = { -+ .inherits = &ahci_ops, -+ .hardreset = ahci_highbank_hardreset, -+}; -+ -+static const struct ata_port_info ahci_highbank_port_info = { -+ .flags = AHCI_FLAG_COMMON, -+ .pio_mask = ATA_PIO4, -+ .udma_mask = ATA_UDMA6, -+ .port_ops = &ahci_highbank_ops, -+}; -+ -+static struct scsi_host_template ahci_highbank_platform_sht = { -+ AHCI_SHT("highbank-ahci"), -+}; -+ -+static const struct of_device_id ahci_of_match[] = { -+ { .compatible = "calxeda,hb-ahci" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, ahci_of_match); -+ -+static int __init ahci_highbank_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct ahci_host_priv *hpriv; -+ struct ata_host *host; -+ struct resource *mem; -+ int irq; -+ int n_ports; -+ int i; -+ int rc; -+ struct ata_port_info pi = ahci_highbank_port_info; -+ const struct ata_port_info *ppi[] = { &pi, NULL }; -+ -+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!mem) { -+ dev_err(dev, "no mmio space\n"); -+ return -EINVAL; -+ } -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq <= 0) { -+ dev_err(dev, "no irq\n"); -+ return -EINVAL; -+ } -+ -+ hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); -+ if (!hpriv) { -+ dev_err(dev, "can't alloc ahci_host_priv\n"); -+ return -ENOMEM; -+ } -+ -+ hpriv->flags |= (unsigned long)pi.private_data; -+ -+ hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem)); -+ if (!hpriv->mmio) { -+ dev_err(dev, "can't map %pR\n", mem); -+ return -ENOMEM; -+ } -+ -+ rc = highbank_initialize_phys(dev, hpriv->mmio); -+ if (rc) -+ return rc; -+ -+ -+ ahci_save_initial_config(dev, hpriv, 0, 0); -+ -+ /* prepare host */ -+ if (hpriv->cap & HOST_CAP_NCQ) -+ pi.flags |= ATA_FLAG_NCQ; -+ -+ if (hpriv->cap & HOST_CAP_PMP) -+ pi.flags |= ATA_FLAG_PMP; -+ -+ ahci_set_em_messages(hpriv, &pi); -+ -+ /* CAP.NP sometimes indicate the index of the last enabled -+ * port, at other times, that of the last possible port, so -+ * determining the maximum port number requires looking at -+ * both CAP.NP and port_map. -+ */ -+ n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); -+ -+ host = ata_host_alloc_pinfo(dev, ppi, n_ports); -+ if (!host) { -+ rc = -ENOMEM; -+ goto err0; -+ } -+ -+ host->private_data = hpriv; -+ -+ if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) -+ host->flags |= ATA_HOST_PARALLEL_SCAN; -+ -+ if (pi.flags & ATA_FLAG_EM) -+ ahci_reset_em(host); -+ -+ for (i = 0; i < host->n_ports; i++) { -+ struct ata_port *ap = host->ports[i]; -+ -+ ata_port_desc(ap, "mmio %pR", mem); -+ ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); -+ -+ /* set enclosure management message type */ -+ if (ap->flags & ATA_FLAG_EM) -+ ap->em_message_type = hpriv->em_msg_type; -+ -+ /* disabled/not-implemented port */ -+ if (!(hpriv->port_map & (1 << i))) -+ ap->ops = &ata_dummy_port_ops; -+ } -+ -+ rc = ahci_reset_controller(host); -+ if (rc) -+ goto err0; -+ -+ ahci_init_controller(host); -+ ahci_print_info(host, "platform"); -+ -+ rc = ata_host_activate(host, irq, ahci_interrupt, 0, -+ &ahci_highbank_platform_sht); -+ if (rc) -+ goto err0; -+ -+ return 0; -+err0: -+ return rc; -+} -+ -+static int __devexit ahci_highbank_remove(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct ata_host *host = dev_get_drvdata(dev); -+ -+ ata_host_detach(host); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int ahci_highbank_suspend(struct device *dev) -+{ -+ struct ata_host *host = dev_get_drvdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ void __iomem *mmio = hpriv->mmio; -+ u32 ctl; -+ int rc; -+ -+ if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { -+ dev_err(dev, "firmware update required for suspend/resume\n"); -+ return -EIO; -+ } -+ -+ /* -+ * AHCI spec rev1.1 section 8.3.3: -+ * Software must disable interrupts prior to requesting a -+ * transition of the HBA to D3 state. -+ */ -+ ctl = readl(mmio + HOST_CTL); -+ ctl &= ~HOST_IRQ_EN; -+ writel(ctl, mmio + HOST_CTL); -+ readl(mmio + HOST_CTL); /* flush */ -+ -+ rc = ata_host_suspend(host, PMSG_SUSPEND); -+ if (rc) -+ return rc; -+ -+ return 0; -+} -+ -+static int ahci_highbank_resume(struct device *dev) -+{ -+ struct ata_host *host = dev_get_drvdata(dev); -+ int rc; -+ -+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) { -+ rc = ahci_reset_controller(host); -+ if (rc) -+ return rc; -+ -+ ahci_init_controller(host); -+ } -+ -+ ata_host_resume(host); -+ -+ return 0; -+} -+#endif -+ -+SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops, -+ ahci_highbank_suspend, ahci_highbank_resume); -+ -+static struct platform_driver ahci_highbank_driver = { -+ .remove = __devexit_p(ahci_highbank_remove), -+ .driver = { -+ .name = "highbank-ahci", -+ .owner = THIS_MODULE, -+ .of_match_table = ahci_of_match, -+ .pm = &ahci_highbank_pm_ops, -+ }, -+ .probe = ahci_highbank_probe, -+}; -+ -+module_platform_driver(ahci_highbank_driver); -+ -+MODULE_DESCRIPTION("Calxeda Highbank AHCI SATA platform driver"); -+MODULE_AUTHOR("Mark Langsdorf <mark.langsdorf@calxeda.com>"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("sata:highbank"); diff --git a/freed-ora/current/f18/block-fix-a-crash-when-block-device-is.patch b/freed-ora/current/f18/block-fix-a-crash-when-block-device-is.patch deleted file mode 100644 index af992830e..000000000 --- a/freed-ora/current/f18/block-fix-a-crash-when-block-device-is.patch +++ /dev/null @@ -1,214 +0,0 @@ -Fix a crash when block device is read and block size is changed at the same time - -commit b87570f5d349661814b262dd5fc40787700f80d6 -Author: Mikulas Patocka <mpatocka@redhat.com> -Date: Wed Sep 26 07:46:40 2012 +0200 - - Fix a crash when block device is read and block size is changed at the same time - - The kernel may crash when block size is changed and I/O is issued - simultaneously. - - Because some subsystems (udev or lvm) may read any block device anytime, - the bug actually puts any code that changes a block device size in - jeopardy. - - The crash can be reproduced if you place "msleep(1000)" to - blkdev_get_blocks just before "bh->b_size = max_blocks << - inode->i_blkbits;". - Then, run "dd if=/dev/ram0 of=/dev/null bs=4k count=1 iflag=direct" - While it is waiting in msleep, run "blockdev --setbsz 2048 /dev/ram0" - You get a BUG. - - The direct and non-direct I/O is written with the assumption that block - size does not change. It doesn't seem practical to fix these crashes - one-by-one there may be many crash possibilities when block size changes - at a certain place and it is impossible to find them all and verify the - code. - - This patch introduces a new rw-lock bd_block_size_semaphore. The lock is - taken for read during I/O. It is taken for write when changing block - size. Consequently, block size can't be changed while I/O is being - submitted. - - For asynchronous I/O, the patch only prevents block size change while - the I/O is being submitted. The block size can change when the I/O is in - progress or when the I/O is being finished. This is acceptable because - there are no accesses to block size when asynchronous I/O is being - finished. - - The patch prevents block size changing while the device is mapped with - mmap. - - Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> - Signed-off-by: Jens Axboe <axboe@kernel.dk> - -Index: linux-3.6.x86_64/drivers/char/raw.c -=================================================================== ---- linux-3.6.x86_64.orig/drivers/char/raw.c 2012-11-16 17:12:35.127010280 -0500 -+++ linux-3.6.x86_64/drivers/char/raw.c 2012-11-16 17:12:37.381002516 -0500 -@@ -285,7 +285,7 @@ - - static const struct file_operations raw_fops = { - .read = do_sync_read, -- .aio_read = generic_file_aio_read, -+ .aio_read = blkdev_aio_read, - .write = do_sync_write, - .aio_write = blkdev_aio_write, - .fsync = blkdev_fsync, -Index: linux-3.6.x86_64/fs/block_dev.c -=================================================================== ---- linux-3.6.x86_64.orig/fs/block_dev.c 2012-11-16 17:12:35.127010280 -0500 -+++ linux-3.6.x86_64/fs/block_dev.c 2012-11-16 17:12:37.381002516 -0500 -@@ -116,6 +116,8 @@ - - int set_blocksize(struct block_device *bdev, int size) - { -+ struct address_space *mapping; -+ - /* Size must be a power of two, and between 512 and PAGE_SIZE */ - if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size)) - return -EINVAL; -@@ -124,6 +126,20 @@ - if (size < bdev_logical_block_size(bdev)) - return -EINVAL; - -+ /* Prevent starting I/O or mapping the device */ -+ down_write(&bdev->bd_block_size_semaphore); -+ -+ /* Check that the block device is not memory mapped */ -+ mapping = bdev->bd_inode->i_mapping; -+ mutex_lock(&mapping->i_mmap_mutex); -+ if (!prio_tree_empty(&mapping->i_mmap) || -+ !list_empty(&mapping->i_mmap_nonlinear)) { -+ mutex_unlock(&mapping->i_mmap_mutex); -+ up_write(&bdev->bd_block_size_semaphore); -+ return -EBUSY; -+ } -+ mutex_unlock(&mapping->i_mmap_mutex); -+ - /* Don't change the size if it is same as current */ - if (bdev->bd_block_size != size) { - sync_blockdev(bdev); -@@ -131,6 +147,9 @@ - bdev->bd_inode->i_blkbits = blksize_bits(size); - kill_bdev(bdev); - } -+ -+ up_write(&bdev->bd_block_size_semaphore); -+ - return 0; - } - -@@ -472,6 +491,7 @@ - inode_init_once(&ei->vfs_inode); - /* Initialize mutex for freeze. */ - mutex_init(&bdev->bd_fsfreeze_mutex); -+ init_rwsem(&bdev->bd_block_size_semaphore); - } - - static inline void __bd_forget(struct inode *inode) -@@ -1567,6 +1587,22 @@ - return blkdev_ioctl(bdev, mode, cmd, arg); - } - -+ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov, -+ unsigned long nr_segs, loff_t pos) -+{ -+ ssize_t ret; -+ struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); -+ -+ down_read(&bdev->bd_block_size_semaphore); -+ -+ ret = generic_file_aio_read(iocb, iov, nr_segs, pos); -+ -+ up_read(&bdev->bd_block_size_semaphore); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(blkdev_aio_read); -+ - /* - * Write data to the block device. Only intended for the block device itself - * and the raw driver which basically is a fake block device. -@@ -1578,12 +1614,16 @@ - unsigned long nr_segs, loff_t pos) - { - struct file *file = iocb->ki_filp; -+ struct block_device *bdev = I_BDEV(file->f_mapping->host); - struct blk_plug plug; - ssize_t ret; - - BUG_ON(iocb->ki_pos != pos); - - blk_start_plug(&plug); -+ -+ down_read(&bdev->bd_block_size_semaphore); -+ - ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); - if (ret > 0 || ret == -EIOCBQUEUED) { - ssize_t err; -@@ -1592,11 +1632,29 @@ - if (err < 0 && ret > 0) - ret = err; - } -+ -+ up_read(&bdev->bd_block_size_semaphore); -+ - blk_finish_plug(&plug); -+ - return ret; - } - EXPORT_SYMBOL_GPL(blkdev_aio_write); - -+int blkdev_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ int ret; -+ struct block_device *bdev = I_BDEV(file->f_mapping->host); -+ -+ down_read(&bdev->bd_block_size_semaphore); -+ -+ ret = generic_file_mmap(file, vma); -+ -+ up_read(&bdev->bd_block_size_semaphore); -+ -+ return ret; -+} -+ - /* - * Try to release a page associated with block device when the system - * is under memory pressure. -@@ -1627,9 +1685,9 @@ - .llseek = block_llseek, - .read = do_sync_read, - .write = do_sync_write, -- .aio_read = generic_file_aio_read, -+ .aio_read = blkdev_aio_read, - .aio_write = blkdev_aio_write, -- .mmap = generic_file_mmap, -+ .mmap = blkdev_mmap, - .fsync = blkdev_fsync, - .unlocked_ioctl = block_ioctl, - #ifdef CONFIG_COMPAT -Index: linux-3.6.x86_64/include/linux/fs.h -=================================================================== ---- linux-3.6.x86_64.orig/include/linux/fs.h 2012-11-16 17:12:35.127010280 -0500 -+++ linux-3.6.x86_64/include/linux/fs.h 2012-11-16 17:12:37.424002387 -0500 -@@ -724,6 +724,8 @@ - int bd_fsfreeze_count; - /* Mutex for freeze */ - struct mutex bd_fsfreeze_mutex; -+ /* A semaphore that prevents I/O while block size is being changed */ -+ struct rw_semaphore bd_block_size_semaphore; - }; - - /* -@@ -2564,6 +2566,8 @@ - unsigned long *nr_segs, size_t *count, int access_flags); - - /* fs/block_dev.c */ -+extern ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov, -+ unsigned long nr_segs, loff_t pos); - extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos); - extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end, diff --git a/freed-ora/current/f18/blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch b/freed-ora/current/f18/blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch deleted file mode 100644 index 82caa6b76..000000000 --- a/freed-ora/current/f18/blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch +++ /dev/null @@ -1,290 +0,0 @@ -blockdev: turn a rw semaphore into a percpu rw semaphore - -commit 62ac665ff9fc07497ca524bd20d6a96893d11071 -Author: Mikulas Patocka <mpatocka@redhat.com> -Date: Wed Sep 26 07:46:43 2012 +0200 - - blockdev: turn a rw semaphore into a percpu rw semaphore - - This avoids cache line bouncing when many processes lock the semaphore - for read. - - New percpu lock implementation - - The lock consists of an array of percpu unsigned integers, a boolean - variable and a mutex. - - When we take the lock for read, we enter rcu read section, check for a - "locked" variable. If it is false, we increase a percpu counter on the - current cpu and exit the rcu section. If "locked" is true, we exit the - rcu section, take the mutex and drop it (this waits until a writer - finished) and retry. - - Unlocking for read just decreases percpu variable. Note that we can - unlock on a difference cpu than where we locked, in this case the - counter underflows. The sum of all percpu counters represents the number - of processes that hold the lock for read. - - When we need to lock for write, we take the mutex, set "locked" variable - to true and synchronize rcu. Since RCU has been synchronized, no - processes can create new read locks. We wait until the sum of percpu - counters is zero - when it is, there are no readers in the critical - section. - - Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> - Signed-off-by: Jens Axboe <axboe@kernel.dk> - -Index: linux-3.6.x86_64/Documentation/percpu-rw-semaphore.txt -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-3.6.x86_64/Documentation/percpu-rw-semaphore.txt 2012-11-16 17:12:57.351936583 -0500 -@@ -0,0 +1,27 @@ -+Percpu rw semaphores -+-------------------- -+ -+Percpu rw semaphores is a new read-write semaphore design that is -+optimized for locking for reading. -+ -+The problem with traditional read-write semaphores is that when multiple -+cores take the lock for reading, the cache line containing the semaphore -+is bouncing between L1 caches of the cores, causing performance -+degradation. -+ -+Locking for reading it very fast, it uses RCU and it avoids any atomic -+instruction in the lock and unlock path. On the other hand, locking for -+writing is very expensive, it calls synchronize_rcu() that can take -+hundreds of microseconds. -+ -+The lock is declared with "struct percpu_rw_semaphore" type. -+The lock is initialized percpu_init_rwsem, it returns 0 on success and -+-ENOMEM on allocation failure. -+The lock must be freed with percpu_free_rwsem to avoid memory leak. -+ -+The lock is locked for read with percpu_down_read, percpu_up_read and -+for write with percpu_down_write, percpu_up_write. -+ -+The idea of using RCU for optimized rw-lock was introduced by -+Eric Dumazet <eric.dumazet@gmail.com>. -+The code was written by Mikulas Patocka <mpatocka@redhat.com> -Index: linux-3.6.x86_64/fs/block_dev.c -=================================================================== ---- linux-3.6.x86_64.orig/fs/block_dev.c 2012-11-16 17:12:37.381002516 -0500 -+++ linux-3.6.x86_64/fs/block_dev.c 2012-11-16 17:27:41.217005828 -0500 -@@ -127,7 +127,7 @@ - return -EINVAL; - - /* Prevent starting I/O or mapping the device */ -- down_write(&bdev->bd_block_size_semaphore); -+ percpu_down_write(&bdev->bd_block_size_semaphore); - - /* Check that the block device is not memory mapped */ - mapping = bdev->bd_inode->i_mapping; -@@ -135,7 +135,7 @@ - if (!prio_tree_empty(&mapping->i_mmap) || - !list_empty(&mapping->i_mmap_nonlinear)) { - mutex_unlock(&mapping->i_mmap_mutex); -- up_write(&bdev->bd_block_size_semaphore); -+ percpu_up_write(&bdev->bd_block_size_semaphore); - return -EBUSY; - } - mutex_unlock(&mapping->i_mmap_mutex); -@@ -148,7 +148,7 @@ - kill_bdev(bdev); - } - -- up_write(&bdev->bd_block_size_semaphore); -+ percpu_up_write(&bdev->bd_block_size_semaphore); - - return 0; - } -@@ -460,6 +460,12 @@ - struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL); - if (!ei) - return NULL; -+ -+ if (unlikely(percpu_init_rwsem(&ei->bdev.bd_block_size_semaphore))) { -+ kmem_cache_free(bdev_cachep, ei); -+ return NULL; -+ } -+ - return &ei->vfs_inode; - } - -@@ -468,6 +474,8 @@ - struct inode *inode = container_of(head, struct inode, i_rcu); - struct bdev_inode *bdi = BDEV_I(inode); - -+ percpu_free_rwsem(&bdi->bdev.bd_block_size_semaphore); -+ - kmem_cache_free(bdev_cachep, bdi); - } - -@@ -491,7 +499,6 @@ - inode_init_once(&ei->vfs_inode); - /* Initialize mutex for freeze. */ - mutex_init(&bdev->bd_fsfreeze_mutex); -- init_rwsem(&bdev->bd_block_size_semaphore); - } - - static inline void __bd_forget(struct inode *inode) -@@ -1593,11 +1600,11 @@ - ssize_t ret; - struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); - -- down_read(&bdev->bd_block_size_semaphore); -+ percpu_down_read(&bdev->bd_block_size_semaphore); - - ret = generic_file_aio_read(iocb, iov, nr_segs, pos); - -- up_read(&bdev->bd_block_size_semaphore); -+ percpu_up_read(&bdev->bd_block_size_semaphore); - - return ret; - } -@@ -1622,7 +1629,7 @@ - - blk_start_plug(&plug); - -- down_read(&bdev->bd_block_size_semaphore); -+ percpu_down_read(&bdev->bd_block_size_semaphore); - - ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); - if (ret > 0 || ret == -EIOCBQUEUED) { -@@ -1633,7 +1640,7 @@ - ret = err; - } - -- up_read(&bdev->bd_block_size_semaphore); -+ percpu_up_read(&bdev->bd_block_size_semaphore); - - blk_finish_plug(&plug); - -@@ -1646,11 +1653,11 @@ - int ret; - struct block_device *bdev = I_BDEV(file->f_mapping->host); - -- down_read(&bdev->bd_block_size_semaphore); -+ percpu_down_read(&bdev->bd_block_size_semaphore); - - ret = generic_file_mmap(file, vma); - -- up_read(&bdev->bd_block_size_semaphore); -+ percpu_up_read(&bdev->bd_block_size_semaphore); - - return ret; - } -Index: linux-3.6.x86_64/include/linux/fs.h -=================================================================== ---- linux-3.6.x86_64.orig/include/linux/fs.h 2012-11-16 17:12:37.424002387 -0500 -+++ linux-3.6.x86_64/include/linux/fs.h 2012-11-16 17:28:12.578901349 -0500 -@@ -415,6 +415,7 @@ - #include <linux/migrate_mode.h> - #include <linux/uidgid.h> - #include <linux/lockdep.h> -+#include <linux/percpu-rwsem.h> - - #include <asm/byteorder.h> - -@@ -725,7 +726,7 @@ - /* Mutex for freeze */ - struct mutex bd_fsfreeze_mutex; - /* A semaphore that prevents I/O while block size is being changed */ -- struct rw_semaphore bd_block_size_semaphore; -+ struct percpu_rw_semaphore bd_block_size_semaphore; - }; - - /* -Index: linux-3.6.x86_64/include/linux/percpu-rwsem.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-3.6.x86_64/include/linux/percpu-rwsem.h 2012-11-16 17:12:57.354936574 -0500 -@@ -0,0 +1,89 @@ -+#ifndef _LINUX_PERCPU_RWSEM_H -+#define _LINUX_PERCPU_RWSEM_H -+ -+#include <linux/mutex.h> -+#include <linux/percpu.h> -+#include <linux/rcupdate.h> -+#include <linux/delay.h> -+ -+struct percpu_rw_semaphore { -+ unsigned __percpu *counters; -+ bool locked; -+ struct mutex mtx; -+}; -+ -+static inline void percpu_down_read(struct percpu_rw_semaphore *p) -+{ -+ rcu_read_lock(); -+ if (unlikely(p->locked)) { -+ rcu_read_unlock(); -+ mutex_lock(&p->mtx); -+ this_cpu_inc(*p->counters); -+ mutex_unlock(&p->mtx); -+ return; -+ } -+ this_cpu_inc(*p->counters); -+ rcu_read_unlock(); -+} -+ -+static inline void percpu_up_read(struct percpu_rw_semaphore *p) -+{ -+ /* -+ * On X86, write operation in this_cpu_dec serves as a memory unlock -+ * barrier (i.e. memory accesses may be moved before the write, but -+ * no memory accesses are moved past the write). -+ * On other architectures this may not be the case, so we need smp_mb() -+ * there. -+ */ -+#if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE)) -+ barrier(); -+#else -+ smp_mb(); -+#endif -+ this_cpu_dec(*p->counters); -+} -+ -+static inline unsigned __percpu_count(unsigned __percpu *counters) -+{ -+ unsigned total = 0; -+ int cpu; -+ -+ for_each_possible_cpu(cpu) -+ total += ACCESS_ONCE(*per_cpu_ptr(counters, cpu)); -+ -+ return total; -+} -+ -+static inline void percpu_down_write(struct percpu_rw_semaphore *p) -+{ -+ mutex_lock(&p->mtx); -+ p->locked = true; -+ synchronize_rcu(); -+ while (__percpu_count(p->counters)) -+ msleep(1); -+ smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */ -+} -+ -+static inline void percpu_up_write(struct percpu_rw_semaphore *p) -+{ -+ p->locked = false; -+ mutex_unlock(&p->mtx); -+} -+ -+static inline int percpu_init_rwsem(struct percpu_rw_semaphore *p) -+{ -+ p->counters = alloc_percpu(unsigned); -+ if (unlikely(!p->counters)) -+ return -ENOMEM; -+ p->locked = false; -+ mutex_init(&p->mtx); -+ return 0; -+} -+ -+static inline void percpu_free_rwsem(struct percpu_rw_semaphore *p) -+{ -+ free_percpu(p->counters); -+ p->counters = NULL; /* catch use after free bugs */ -+} -+ -+#endif diff --git a/freed-ora/current/f18/config-arm-generic b/freed-ora/current/f18/config-arm-generic index d44eda51d..89fc4356a 100644 --- a/freed-ora/current/f18/config-arm-generic +++ b/freed-ora/current/f18/config-arm-generic @@ -12,6 +12,7 @@ CONFIG_AEABI=y CONFIG_OABI_COMPAT=y CONFIG_VFP=y CONFIG_ARM_UNWIND=y +# CONFIG_ARCH_MULTI_V7 is not set CONFIG_SMP=y CONFIG_NR_CPUS=4 @@ -27,6 +28,7 @@ CONFIG_FPE_FASTFPE=y CONFIG_HIGHPTE=y CONFIG_HW_PERF_EVENTS=y CONFIG_UACCESS_WITH_MEMCPY=y +# CONFIG_GENERIC_CPUFREQ_CPU0 is not set # Generic ARM Errata CONFIG_ARM_ERRATA_720789=y @@ -35,13 +37,14 @@ CONFIG_ARM_ERRATA_742230=y CONFIG_ARM_ERRATA_742231=y CONFIG_ARM_ERRATA_754327=y CONFIG_ARM_ERRATA_764369=y - +CONFIG_ARM_ERRATA_775420=y # Generic ARM config options CONFIG_ZBOOT_ROM_TEXT=0 CONFIG_ZBOOT_ROM_BSS=0 CONFIG_LOCAL_TIMERS=y +CONFIG_ATAGS=y CONFIG_ATAGS_PROC=y CONFIG_PL330_DMA=y @@ -63,9 +66,6 @@ CONFIG_CPU_IDLE=y # CONFIG_CPU_IDLE_GOV_LADDER is not set CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 -CONFIG_LSM_MMAP_MIN_ADDR=32768 - CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -75,6 +75,16 @@ CONFIG_SUSPEND=y CONFIG_ARM_CPU_SUSPEND=y CONFIG_ARM_CPU_TOPOLOGY=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +CONFIG_LSM_MMAP_MIN_ADDR=32768 + +# CONFIG_XEN is not set + +CONFIG_PINCTRL=y +CONFIG_PINCONF=y + +CONFIG_COMMON_CLK=y + CONFIG_THERMAL=y CONFIG_ETHERNET=y @@ -84,24 +94,20 @@ CONFIG_PERF_COUNTERS=y CONFIG_CC_STACKPROTECTOR=y -CONFIG_AUTO_ZRELADDR=y - CONFIG_SECCOMP=y CONFIG_STRICT_DEVMEM=y CONFIG_SPARSE_IRQ=y # Generic HW for all ARM platforms -CONFIG_LEDS=y -CONFIG_LEDS_CPU=y CONFIG_LEDS_GPIO=m CONFIG_LBDAF=y +CONFIG_GPIOLIB=y CONFIG_RFKILL_GPIO=m CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y CONFIG_GPIO_GENERIC_PLATFORM=m -CONFIG_GPIOLIB=y CONFIG_PINCTRL_SINGLE=m CONFIG_USB_ULPI=y @@ -136,10 +142,13 @@ CONFIG_MMC_SPI=m CONFIG_MMC_DW=m CONFIG_MMC_DW_PLTFM=m CONFIG_MMC_DW_PCI=m +# CONFIG_MMC_DW_EXYNOS is not set # CONFIG_MMC_DW_IDMAC is not set CONFIG_MMC_SDHCI_PXAV3=m CONFIG_MMC_SDHCI_PXAV2=m +# CONFIG_DW_DMAC_BIG_ENDIAN_IO is not set + # Generic GPIO options CONFIG_GENERIC_GPIO=y @@ -234,12 +243,15 @@ CONFIG_UBIFS_FS_ZLIB=y # CONFIG_UBIFS_FS_DEBUG is not set # HW crypto and rng +CONFIG_CRYPTO_SHA1_ARM=m +CONFIG_CRYPTO_AES_ARM=m CONFIG_HW_RANDOM_ATMEL=m CONFIG_HW_RANDOM_EXYNOS=m # Device tree CONFIG_OF=y CONFIG_USE_OF=y +CONFIG_OF_IRQ=y CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_ARM_APPENDED_DTB=y CONFIG_PROC_DEVICETREE=y @@ -252,6 +264,7 @@ CONFIG_OF_PCI_IRQ=y CONFIG_I2C_MUX_PINCTRL=m CONFIG_OF_MDIO=m CONFIG_MDIO_BUS_MUX_GPIO=m +CONFIG_MDIO_BUS_MUX_MMIOREG=m CONFIG_BPF_JIT=y @@ -263,6 +276,7 @@ CONFIG_EDAC_LEGACY_SYSFS=y CONFIG_RTC_DRV_88PM80X=m CONFIG_RTC_DRV_PL030=m CONFIG_RTC_DRV_PL031=m +CONFIG_RTC_DRV_SNVS=m CONFIG_RFKILL_REGULATOR=m CONFIG_INPUT_88PM80X_ONKEY=y CONFIG_INPUT_GP2A=m @@ -272,14 +286,22 @@ CONFIG_SERIAL_AMBA_PL010=m CONFIG_SERIAL_AMBA_PL011=m CONFIG_GPIO_PL061=y CONFIG_GPIO_MCP23S08=m +CONFIG_GPIO_ADNP=m CONFIG_PL310_ERRATA_753970=y CONFIG_MFD_88PM800=m CONFIG_MFD_88PM805=m +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_MAX8907 is not set + CONFIG_REGULATOR_VIRTUAL_CONSUMER=m CONFIG_REGULATOR_USERSPACE_CONSUMER=m CONFIG_REGULATOR_GPIO=m CONFIG_REGULATOR_AD5398=m +CONFIG_REGULATOR_ANATOP=m +CONFIG_REGULATOR_FAN53555=m CONFIG_REGULATOR_ISL6271A=m CONFIG_REGULATOR_MAX1586=m CONFIG_REGULATOR_MAX8649=m @@ -292,6 +314,12 @@ CONFIG_REGULATOR_TPS6507X=m CONFIG_CHARGER_MANAGER=y CONFIG_EXTCON_GPIO=m +# CONFIG_ARM_VIRT_EXT is not set +# CONFIG_PINCTRL_EXYNOS4 is not set + +# CONFIG_AUTO_ZRELADDR is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set + # CONFIG_VFIO is not set # CONFIG_XIP_KERNEL is not set @@ -356,3 +384,4 @@ CONFIG_EXTCON_GPIO=m # CONFIG_NET_VENDOR_CIRRUS is not set # CONFIG_CS89x0 is not set +# CONFIG_DVB_USB_PCTV452E is not set diff --git a/freed-ora/current/f18/config-arm-highbank b/freed-ora/current/f18/config-arm-highbank index 952a21ac4..ca27f65cb 100644 --- a/freed-ora/current/f18/config-arm-highbank +++ b/freed-ora/current/f18/config-arm-highbank @@ -59,4 +59,7 @@ CONFIG_OC_ETM=y # CONFIG_MEDIA_SUPPORT is not set # CONFIG_DRM is not set # CONFIG_SND is not set +# CONFIG_ARCH_MULTI_V4 is not set +# CONFIG_ARCH_MULTI_V4T is not set +# CONFIG_ARCH_MULTI_V6 is not set # end of list of requested disabled options diff --git a/freed-ora/current/f18/config-arm-imx b/freed-ora/current/f18/config-arm-imx index bddff88ab..8ffd96559 100644 --- a/freed-ora/current/f18/config-arm-imx +++ b/freed-ora/current/f18/config-arm-imx @@ -7,6 +7,7 @@ CONFIG_NEON=y # CONFIG_THUMB2_KERNEL is not set CONFIG_CPU_FREQ_IMX=y +CONFIG_SOC_IMX53=y CONFIG_SOC_IMX6Q=y CONFIG_MACH_ARMADILLO5X0=y @@ -67,6 +68,7 @@ CONFIG_I2C_IMX=m CONFIG_GPIO_GENERIC_PLATFORM=y CONFIG_GPIO_MCP23S08=m # CONFIG_GPIO_MC9S08DZ60 is not set +CONFIG_PINCTRL_IMX35=y CONFIG_PINCTRL_IMX51=y CONFIG_PINCTRL_IMX53=y CONFIG_USB_EHCI_MXC=y @@ -77,6 +79,12 @@ CONFIG_MMC_MXC=m CONFIG_RTC_MXC=y CONFIG_RTC_DRV_MXC=m +CONFIG_DRM_IMX=m +CONFIG_DRM_IMX_FB_HELPER=m +CONFIG_DRM_IMX_PARALLEL_DISPLAY=m +CONFIG_DRM_IMX_IPUV3_CORE=m +CONFIG_DRM_IMX_IPUV3=m +CONFIG_VIDEO_CODA=m CONFIG_BACKLIGHT_PWM=m CONFIG_LEDS_PWM=m @@ -104,6 +112,8 @@ CONFIG_SND_SOC_IMX_SGTL5000=m CONFIG_PL310_ERRATA_769419=y CONFIG_LEDS_RENESAS_TPU=y +CONFIG_MFD_MAX8907=m + CONFIG_FB_IMX=m # CONFIG_NET_VENDOR_BROADCOM is not set diff --git a/freed-ora/current/f18/config-arm-kirkwood b/freed-ora/current/f18/config-arm-kirkwood index c8d0ec181..ff1dad7df 100644 --- a/freed-ora/current/f18/config-arm-kirkwood +++ b/freed-ora/current/f18/config-arm-kirkwood @@ -6,6 +6,7 @@ CONFIG_ARCH_KIRKWOOD_DT=y CONFIG_MACH_D2NET_V2=y CONFIG_MACH_DB88F6281_BP=y CONFIG_MACH_DOCKSTAR=y +CONFIG_MACH_DOCKSTAR_DT=y CONFIG_MACH_DREAMPLUG_DT=y CONFIG_MACH_ESATA_SHEEVAPLUG=y CONFIG_MACH_DLINK_KIRKWOOD_DT=y @@ -14,6 +15,8 @@ CONFIG_MACH_GURUPLUG=y CONFIG_MACH_ICONNECT_DT=y CONFIG_MACH_IB62X0_DT=y CONFIG_MACH_INETSPACE_V2=y +CONFIG_MACH_IOMEGA_IX2_200_DT=y +CONFIG_MACH_KM_KIRKWOOD_DT=y CONFIG_MACH_LSXL_DT=y CONFIG_MACH_MV88F6281GTW_GE=y CONFIG_MACH_NETSPACE_V2=y @@ -48,6 +51,8 @@ CONFIG_LEDS_NETXBIG=m CONFIG_RTC_DRV_MV=y CONFIG_MV_XOR=y CONFIG_CRYPTO_DEV_MV_CESA=m +CONFIG_PINCTRL_MVEBU=y +CONFIG_PINCTRL_KIRKWOOD=y # CONFIG_CPU_FEROCEON_OLD_ID is not set # CONFIG_INPUT_GP2A is not set diff --git a/freed-ora/current/f18/config-arm-omap b/freed-ora/current/f18/config-arm-omap index 8e314ce1d..68421b06e 100644 --- a/freed-ora/current/f18/config-arm-omap +++ b/freed-ora/current/f18/config-arm-omap @@ -176,6 +176,7 @@ CONFIG_TWL4030_POWER=y CONFIG_TWL4030_CODEC=y CONFIG_TWL4030_WATCHDOG=m CONFIG_GPIO_TWL4030=m +CONFIG_GPIO_TWL6040=m CONFIG_CHARGER_TWL4030=m CONFIG_TWL6030_PWM=m CONFIG_TWL6040_CORE=y @@ -185,19 +186,23 @@ CONFIG_TI_DAVINCI_MDIO=m CONFIG_TI_DAVINCI_CPDMA=m CONFIG_LEDS_PWM=m +CONFIG_LEDS_LP8788=m CONFIG_MTD_ONENAND_OMAP2=y CONFIG_HDQ_MASTER_OMAP=m CONFIG_I2C_OMAP=m CONFIG_SPI_OMAP24XX=y CONFIG_MFD_OMAP_USB_HOST=y CONFIG_MFD_WL1273_CORE=m +CONFIG_MFD_LP8788=y CONFIG_REGULATOR_TWL4030=y +CONFIG_REGULATOR_LP8788=y # Enable V4L2 drivers for OMAP2+ CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_VIDEO_VPFE_CAPTURE=m CONFIG_VIDEO_OMAP2_VOUT=m +CONFIG_VIDEO_DM6446_CCDC=m # CONFIG_VIDEO_OMAP3 is not set # Also enable vivi driver - useful for testing a full kernelspace V4L2 driver CONFIG_V4L_TEST_DRIVERS=y @@ -228,6 +233,7 @@ CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET=y CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y CONFIG_PANEL_TFP410=m +CONFIG_PANEL_TAAL=m CONFIG_PANEL_PICODLP=m CONFIG_BACKLIGHT_PANDORA=m @@ -240,21 +246,22 @@ CONFIG_PANEL_NEC_NL8048HL11_01B=y CONFIG_PANEL_TPO_TD043MTEA1=y CONFIG_SND_OMAP_SOC=y -CONFIG_SND_OMAP_SOC_MCBSP=y -CONFIG_SND_OMAP_SOC_MCPDM=y -CONFIG_SND_OMAP_SOC_OVERO=y -CONFIG_SND_OMAP_SOC_OMAP3EVM=y -CONFIG_SND_OMAP_SOC_AM3517EVM=y -CONFIG_SND_OMAP_SOC_SDP3430=y -CONFIG_SND_OMAP_SOC_SDP4430=y -CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y -CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y -CONFIG_SND_OMAP_SOC_ZOOM2=y +CONFIG_SND_OMAP_SOC_MCBSP=m +CONFIG_SND_OMAP_SOC_MCPDM=m +CONFIG_SND_OMAP_SOC_OVERO=m +CONFIG_SND_OMAP_SOC_OMAP3EVM=m +CONFIG_SND_OMAP_SOC_AM3517EVM=m +CONFIG_SND_OMAP_SOC_SDP3430=m +CONFIG_SND_OMAP_SOC_SDP4430=m +CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m +CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=m +CONFIG_SND_OMAP_SOC_ZOOM2=m CONFIG_SND_OMAP_SOC_IGEP0020=y CONFIG_SND_OMAP_SOC_OMAP_HDMI=y # Because alsa is modular http://www.spinics.net/lists/linux-omap/msg67307.html # CONFIG_SND_OMAP_SOC_OMAP4_HDMI is not set CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m +CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_OMAP_SOC_RX51 is not set # CONFIG_SND_SOC_ALL_CODECS is not set @@ -292,19 +299,21 @@ CONFIG_TWL4030_USB=y CONFIG_TWL6030_USB=y CONFIG_RTC_DRV_TWL4030=y -CONFIG_TIDSPBRIDGE=m -CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE=0x600000 +CONFIG_IR_RX51=m + +# CONFIG_TIDSPBRIDGE is not set +# CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE=0x600000 # CONFIG_TIDSPBRIDGE_DEBUG is not set -CONFIG_TIDSPBRIDGE_RECOVERY=y +# CONFIG_TIDSPBRIDGE_RECOVERY=y # CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK is not set -CONFIG_TIDSPBRIDGE_WDT3=y -CONFIG_TIDSPBRIDGE_WDT_TIMEOUT=5 +# CONFIG_TIDSPBRIDGE_WDT3=y +# CONFIG_TIDSPBRIDGE_WDT_TIMEOUT=5 # CONFIG_TIDSPBRIDGE_NTFY_PWRERR is not set # CONFIG_TIDSPBRIDGE_BACKTRACE is not set -CONFIG_OMAP_REMOTEPROC=m -CONFIG_OMAP_BANDGAP=m -CONFIG_OMAP_IOVMM=m +# CONFIG_OMAP_REMOTEPROC is not set +# CONFIG_OMAP_BANDGAP is not set +# CONFIG_OMAP_IOVMM is not set CONFIG_CRYPTO_DEV_OMAP_SHAM=m CONFIG_CRYPTO_DEV_OMAP_AES=m diff --git a/freed-ora/current/f18/config-arm-tegra b/freed-ora/current/f18/config-arm-tegra index 78ddf0722..894b5dbef 100644 --- a/freed-ora/current/f18/config-arm-tegra +++ b/freed-ora/current/f18/config-arm-tegra @@ -18,7 +18,6 @@ CONFIG_MACH_WARIO=y CONFIG_MACH_VENTANA=y CONFIG_TEGRA_DEBUG_UARTD=y -CONFIG_NR_CPUS=4 CONFIG_ARM_CPU_TOPOLOGY=y CONFIG_TEGRA_IOMMU_GART=y diff --git a/freed-ora/current/f18/config-arm-versatile b/freed-ora/current/f18/config-arm-versatile index 89d4f7b09..758a78c76 100644 --- a/freed-ora/current/f18/config-arm-versatile +++ b/freed-ora/current/f18/config-arm-versatile @@ -95,3 +95,8 @@ CONFIG_PATA_OF_PLATFORM=m # unset on versatille for jon masters # CONFIG_GPIOLIB is not set +# CONFIG_ARCH_MULTI_V4 is not set +# CONFIG_ARCH_MULTI_V4T is not set +# CONFIG_ARCH_MULTI_V6 is not set +# CONFIG_DRM_EXYNOS is not set + diff --git a/freed-ora/current/f18/config-generic b/freed-ora/current/f18/config-generic index 23d6425b4..a60e6094d 100644 --- a/freed-ora/current/f18/config-generic +++ b/freed-ora/current/f18/config-generic @@ -190,30 +190,76 @@ CONFIG_EXTRA_FIRMWARE="" # Memory Technology Devices (MTD) # CONFIG_MTD=m +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_CHAR is not set +# CONFIG_MTD_BLKDEVS is not set +# CONFIG_MTD_BLOCK is not set +# CONFIG_MTD_BLOCK_RO is not set # CONFIG_FTL is not set # CONFIG_NFTL is not set # CONFIG_INFTL is not set # CONFIG_RFD_FTL is not set # CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set # CONFIG_MTD_OOPS is not set # CONFIG_MTD_SWAP is not set + +# +# RAM/ROM/Flash chip drivers +# # CONFIG_MTD_CFI is not set # CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# # CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_TS5500 is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set + +# Self-contained MTD device drivers +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# # CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set # CONFIG_MTD_NAND_VERIFY_WRITE is not set # CONFIG_MTD_NAND_ECC_BCH is not set # CONFIG_MTD_NAND_MUSEUM_IDS is not set # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_LPDDR is not set CONFIG_MTD_UBI=m - +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_LIMIT=20 +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set # # Parallel port support @@ -433,6 +479,7 @@ CONFIG_ATA_BMDMA=y CONFIG_ATA_VERBOSE_ERROR=y CONFIG_ATA_SFF=y CONFIG_ATA_PIIX=y +# CONFIG_SATA_HIGHBANK is not set CONFIG_ATA_ACPI=y CONFIG_BLK_DEV_SX8=m CONFIG_PDC_ADMA=m @@ -603,6 +650,7 @@ CONFIG_TCP_MD5SIG=y # Networking options # CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set CONFIG_UNIX=y CONFIG_UNIX_DIAG=m CONFIG_NET_KEY=m @@ -682,6 +730,7 @@ CONFIG_IPV6_MIP6=y CONFIG_IPV6_SIT=m CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_TUNNEL=m +# CONFIG_IPV6_GRE is not set CONFIG_IPV6_SUBTREES=y CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_IPV6_MROUTE=y @@ -825,7 +874,6 @@ CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_RPFILTER=m CONFIG_IP_NF_MATCH_TTL=m CONFIG_IP_NF_TARGET_CLUSTERIP=m -CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_ECN=m @@ -833,6 +881,8 @@ CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_REJECT=y CONFIG_IP_NF_TARGET_TTL=m +CONFIG_NF_NAT_IPV4=m +CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m @@ -864,6 +914,9 @@ CONFIG_IP6_NF_SECURITY=m CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_TARGET_REJECT=m CONFIG_IP6_NF_TARGET_HL=m +CONFIG_NF_NAT_IPV6=m +# CONFIG_IP6_NF_TARGET_MASQUERADE is not set +# CONFIG_IP6_NF_TARGET_NPT is not set # # Bridge: Netfilter Configuration @@ -1053,6 +1106,7 @@ CONFIG_DUMMY=m CONFIG_BONDING=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m +CONFIG_VXLAN=m CONFIG_EQUALIZER=m CONFIG_TUN=m CONFIG_VETH=m @@ -1305,6 +1359,7 @@ CONFIG_NET_VENDOR_XIRCOM=y CONFIG_PCMCIA_XIRC2PS=m CONFIG_PHYLIB=y +CONFIG_AT803X_PHY=m CONFIG_AMD_PHY=m CONFIG_BROADCOM_PHY=m CONFIG_BCM87XX_PHY=m @@ -1360,6 +1415,7 @@ CONFIG_MLX4_EN_DCB=y CONFIG_SFC=m CONFIG_SFC_MCDI_MON=y CONFIG_SFC_SRIOV=y +CONFIG_SFC_PTP=y # CONFIG_SFC_MTD is not set @@ -1474,6 +1530,7 @@ CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC_SDIO=y CONFIG_BRCMFMAC_SDIO_OOB=y CONFIG_BRCMFMAC_USB=y +# CONFIG_BRCMISCAN is not set # CONFIG_BRCMDBG is not set # CONFIG_HERMES is not set # CONFIG_HOSTAP is not set @@ -2020,6 +2077,7 @@ CONFIG_TIFM_CORE=m CONFIG_TIFM_7XX1=m CONFIG_TCG_TPM=m CONFIG_TCG_TIS=m +# CONFIG_TCG_TIS_I2C_INFINEON is not set CONFIG_TCG_NSC=m CONFIG_TCG_ATMEL=m # CONFIG_TCG_INFINEON is not set @@ -2046,6 +2104,7 @@ CONFIG_CYCLADES=m # CONFIG_ISI is not set # CONFIG_RIO is not set CONFIG_SERIAL_JSM=m +# CONFIG_SERIAL_SCCNXP is not set # CONFIG_SERIAL_MFD_HSU is not set # CONFIG_SERIAL_ALTERA_JTAGUART is not set @@ -2054,6 +2113,7 @@ CONFIG_SERIAL_JSM=m # # Non-8250 serial port support # +# CONFIG_SERIAL_KGDB_NMI is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_XILINX_PS_UART is not set @@ -2142,6 +2202,7 @@ CONFIG_SENSORS_ADM1026=m CONFIG_SENSORS_ADM1029=m CONFIG_SENSORS_ADM1031=m CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADT7410=m CONFIG_SENSORS_ADS7828=m CONFIG_SENSORS_ADT7462=m CONFIG_SENSORS_ADT7470=m @@ -2261,6 +2322,7 @@ CONFIG_SENSORS_LTC2978=m CONFIG_SENSORS_MAX34440=m CONFIG_SENSORS_MAX8688=m CONFIG_SENSORS_MAX1668=m +CONFIG_SENSORS_MAX197=m # CONFIG_HMC6352 is not set # CONFIG_BMP085 is not set @@ -2275,6 +2337,7 @@ CONFIG_W1_CON=y CONFIG_W1_MASTER_DS2490=m CONFIG_W1_MASTER_DS2482=m CONFIG_W1_MASTER_DS1WM=m +# CONFIG_HDQ_MASTER_OMAP is not set CONFIG_W1_SLAVE_THERM=m CONFIG_W1_SLAVE_SMEM=m CONFIG_W1_SLAVE_DS2408=m @@ -2346,6 +2409,7 @@ CONFIG_W83697UG_WDT=m CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_TIMERIOMEM=m +CONFIG_HW_RANDOM_TPM=m # CONFIG_NVRAM is not set # CONFIG_RTC is not set # CONFIG_RTC_DEBUG is not set @@ -2379,6 +2443,7 @@ CONFIG_RTC_DRV_RS5C372=m # CONFIG_RTC_DRV_TEST is not set CONFIG_RTC_DRV_X1205=m CONFIG_RTC_DRV_V3020=m +CONFIG_RTC_DRV_DS2404=m CONFIG_RTC_DRV_STK17TA8=m # CONFIG_RTC_DRV_S35390A is not set CONFIG_RTC_DRV_RX8581=m @@ -2436,6 +2501,8 @@ CONFIG_DRM_I915=m CONFIG_DRM_I915_KMS=y CONFIG_DRM_VIA=m CONFIG_DRM_NOUVEAU=m +CONFIG_NOUVEAU_DEBUG=5 +CONFIG_NOUVEAU_DEBUG_DEFAULT=3 CONFIG_DRM_NOUVEAU_BACKLIGHT=y CONFIG_DRM_NOUVEAU_DEBUG=y # CONFIG_DRM_PSB is not set @@ -2443,6 +2510,7 @@ CONFIG_DRM_I2C_CH7006=m CONFIG_DRM_I2C_SIL164=m CONFIG_DRM_UDL=m CONFIG_DRM_VMWGFX=m +# CONFIG_DRM_VMWGFX_FBCON is not set CONFIG_DRM_VGEM=m # @@ -2458,6 +2526,8 @@ CONFIG_RAW_DRIVER=y CONFIG_MAX_RAW_DEVS=8192 CONFIG_HANGCHECK_TIMER=m +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_MEDIA_PCI_SUPPORT=y # # Multimedia devices # @@ -2515,6 +2585,7 @@ CONFIG_VIDEO_CX231XX_RC=y CONFIG_VIDEO_HEXIUM_ORION=m CONFIG_VIDEO_HEXIUM_GEMINI=m CONFIG_VIDEO_IVTV=m +# CONFIG_VIDEO_IVTV_ALSA is not set CONFIG_VIDEO_MEYE=m CONFIG_VIDEO_MXB=m CONFIG_VIDEO_PVRUSB2_DVB=y @@ -2526,6 +2597,8 @@ CONFIG_VIDEO_SAA7134_ALSA=m CONFIG_VIDEO_SAA7134_DVB=m CONFIG_VIDEO_SAA7134_RC=y CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_STK1160=m +CONFIG_VIDEO_STK1160_AC97=y CONFIG_VIDEO_W9966=m CONFIG_VIDEO_ZORAN=m CONFIG_VIDEO_ZORAN_AVS6EYES=m @@ -2589,6 +2662,7 @@ CONFIG_DVB_BT8XX=m CONFIG_DVB_BUDGET_CORE=m CONFIG_DVB_PLUTO2=m CONFIG_SMS_SIANO_MDTV=m +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y CONFIG_SMS_USB_DRV=m CONFIG_SMS_SDIO_DRV=m CONFIG_DVB_TTUSB_DEC=m @@ -2606,6 +2680,7 @@ CONFIG_DVB_FIREDTV=m CONFIG_DVB_NGENE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_USB_TECHNISAT_USB2=m +# CONFIG_DVB_USB_V2 is not set CONFIG_DVB_AV7110=m CONFIG_DVB_AV7110_OSD=y @@ -2618,7 +2693,10 @@ CONFIG_DVB_TTUSB_BUDGET=m CONFIG_DVB_USB_CINERGY_T2=m CONFIG_DVB_B2C2_FLEXCOP=m +# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set + CONFIG_DVB_B2C2_FLEXCOP_PCI=m +# CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG is not set CONFIG_DVB_B2C2_FLEXCOP_USB=m # CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set CONFIG_DVB_USB=m @@ -2690,9 +2768,13 @@ CONFIG_IR_ENE=m CONFIG_IR_STREAMZAP=m CONFIG_IR_WINBOND_CIR=m CONFIG_IR_IGUANA=m +CONFIG_IR_TTUSBIR=m CONFIG_IR_GPIO_CIR=m CONFIG_V4L_MEM2MEM_DRIVERS=y +# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set +# CONFIG_V4L_TEST_DRIVERS is not set + # CONFIG_VIDEO_MEM2MEM_TESTDEV is not set # @@ -3067,6 +3149,7 @@ CONFIG_HID_MULTITOUCH=m CONFIG_HID_NTRIG=y CONFIG_HID_QUANTA=y CONFIG_HID_PRIMAX=m +CONFIG_HID_PS3REMOTE=m CONFIG_HID_PRODIKEYS=m CONFIG_HID_DRAGONRISE=m CONFIG_HID_GYRATION=m @@ -3086,6 +3169,7 @@ CONFIG_HID_TOPSEED=m CONFIG_HID_THRUSTMASTER=m CONFIG_HID_ZEROPLUS=m CONFIG_HID_ZYDACRON=m +# CONFIG_HID_SENSOR_HUB is not set CONFIG_HID_EMS_FF=m CONFIG_HID_ELECOM=m CONFIG_HID_UCLOGIC=m @@ -3277,6 +3361,7 @@ CONFIG_USB_SERIAL_MCT_U232=m CONFIG_USB_SERIAL_MOS7720=m CONFIG_USB_SERIAL_MOS7715_PARPORT=y # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_ZTE is not set CONFIG_USB_SERIAL_MOS7840=m CONFIG_USB_SERIAL_MOTOROLA=m CONFIG_USB_SERIAL_NAVMAN=m @@ -3317,6 +3402,7 @@ CONFIG_USB_ADUTUX=m CONFIG_USB_SEVSEG=m CONFIG_USB_ALI_M5632=y CONFIG_USB_APPLEDISPLAY=m +# CONFIG_OMAP_USB2 is not set CONFIG_USB_ATM=m CONFIG_USB_CXACRU=m # CONFIG_USB_C67X00_HCD is not set @@ -3335,6 +3421,7 @@ CONFIG_USB_FILE_STORAGE=m CONFIG_USB_IOWARRIOR=m CONFIG_USB_ISIGHTFW=m CONFIG_USB_YUREX=m +CONFIG_USB_EZUSB_FX2=m CONFIG_USB_LCD=m CONFIG_USB_LD=m CONFIG_USB_LEGOTOWER=m @@ -3585,6 +3672,7 @@ CONFIG_RPCSEC_GSS_KRB5=m CONFIG_CIFS=m CONFIG_CIFS_STATS=y # CONFIG_CIFS_STATS2 is not set +CONFIG_CIFS_SMB2=y CONFIG_CIFS_UPCALL=y CONFIG_CIFS_XATTR=y CONFIG_CIFS_POSIX=y @@ -3756,6 +3844,7 @@ CONFIG_DEBUG_NX_TEST=m CONFIG_DEBUG_SET_MODULE_RONX=y CONFIG_DEBUG_BOOT_PARAMS=y CONFIG_DEBUG_VM=y +# CONFIG_DEBUG_VM_RB is not set # revisit this if performance isn't horrible # CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set CONFIG_LOCKUP_DETECTOR=y # CONFIG_DEBUG_INFO_REDUCED is not set @@ -3769,7 +3858,6 @@ CONFIG_CROSS_MEMORY_ATTACH=y # CONFIG_BACKTRACE_SELF_TEST is not set CONFIG_LATENCYTOP=y CONFIG_RESOURCE_COUNTERS=y -# CONFIG_MEMCG is not set # CONFIG_COMPAT_BRK is not set # CONFIG_DEBUG_VIRTUAL is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set @@ -3920,6 +4008,8 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=m CONFIG_BACKLIGHT_PROGEAR=m # CONFIG_BACKLIGHT_ADP8860 is not set # CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630 is not set +# CONFIG_BACKLIGHT_LM3639 is not set CONFIG_FB_NVIDIA_BACKLIGHT=y CONFIG_FB_RIVA_BACKLIGHT=y CONFIG_FB_RADEON_BACKLIGHT=y @@ -3971,10 +4061,15 @@ CONFIG_KEXEC=y CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set CONFIG_THERMAL_HWMON=y +# CONFIG_CPU_THERMAL is not set CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y +# +# Bus devices +# +# CONFIG_OMAP_OCP2SCP is not set CONFIG_CONNECTOR=y CONFIG_PROC_EVENTS=y @@ -4009,6 +4104,8 @@ CONFIG_NET_VENDOR_SMC=y # CONFIG_MOUSE_ATIXL is not set +# CONFIG_MEDIA_PARPORT_SUPPORT is not set + CONFIG_RADIO_ADAPTERS=y CONFIG_RADIO_TEA5764=m CONFIG_RADIO_SAA7706H=m @@ -4055,6 +4152,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_PCA9633 is not set CONFIG_LEDS_DELL_NETBOOKS=m # CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=m @@ -4062,12 +4160,14 @@ CONFIG_LEDS_TRIGGER_ONESHOT=m CONFIG_LEDS_TRIGGER_IDE_DISK=y CONFIG_LEDS_TRIGGER_HEARTBEAT=m CONFIG_LEDS_TRIGGER_BACKLIGHT=m +# CONFIG_LEDS_TRIGGER_CPU is not set CONFIG_LEDS_TRIGGER_DEFAULT_ON=m CONFIG_LEDS_TRIGGER_TRANSIENT=m CONFIG_LEDS_ALIX2=m CONFIG_LEDS_CLEVO_MAIL=m CONFIG_LEDS_INTEL_SS4200=m CONFIG_LEDS_LM3530=m +# CONFIG_LEDS_LM3642 is not set CONFIG_LEDS_LM3556=m CONFIG_LEDS_BLINKM=m CONFIG_LEDS_LP3944=m @@ -4101,6 +4201,8 @@ CONFIG_FTRACE_MCOUNT_RECORD=y # CONFIG_TRACE_BRANCH_PROFILING is not set CONFIG_FUNCTION_PROFILER=y CONFIG_RING_BUFFER_BENCHMARK=m +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set CONFIG_FUNCTION_TRACER=y CONFIG_STACK_TRACER=y # CONFIG_FUNCTION_GRAPH_TRACER is not set @@ -4316,9 +4418,19 @@ CONFIG_ALTERA_STAPL=m # CONFIG_WIMAX_GDM72XX is not set # CONFIG_IPACK_BUS is not set # CONFIG_CSR_WIFI is not set -# +# CONFIG_ZCACHE2 is not set +# CONFIG_NET_VENDOR_SILICOM is not set +# CONFIG_SBYPASS is not set +# CONFIG_BPCTL is not set +# CONFIG_CED1401 is not set +# CONFIG_DGRP is not set # END OF STAGING +# +# Remoteproc drivers (EXPERIMENTAL) +# +# CONFIG_STE_MODEM_RPROC is not set + CONFIG_LIBFC=m CONFIG_LIBFCOE=m CONFIG_FCOE=m diff --git a/freed-ora/current/f18/config-powerpc-generic b/freed-ora/current/f18/config-powerpc-generic index a263acc80..a6ef1c4df 100644 --- a/freed-ora/current/f18/config-powerpc-generic +++ b/freed-ora/current/f18/config-powerpc-generic @@ -372,3 +372,11 @@ CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_FAIL_IOMMU is not set + +# CONFIG_PPC_DENORMALISATION is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_RTC_DRV_SNVS is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set + diff --git a/freed-ora/current/f18/config-powerpc64 b/freed-ora/current/f18/config-powerpc64 index 82f4c603b..7c0477cf1 100644 --- a/freed-ora/current/f18/config-powerpc64 +++ b/freed-ora/current/f18/config-powerpc64 @@ -167,7 +167,10 @@ CONFIG_HW_RANDOM_AMD=m CONFIG_UIO_PDRV=m CONFIG_HW_RANDOM_PSERIES=m -CONFIG_CRYPTO_DEV_NX=m +CONFIG_CRYPTO_DEV_NX=y +CONFIG_CRYPTO_842=m +CONFIG_CRYPTO_DEV_NX_ENCRYPT=m +CONFIG_CRYPTO_DEV_NX_COMPRESS=m CONFIG_BPF_JIT=y diff --git a/freed-ora/current/f18/config-powerpc64p7 b/freed-ora/current/f18/config-powerpc64p7 index e8e826a88..9a8289588 100644 --- a/freed-ora/current/f18/config-powerpc64p7 +++ b/freed-ora/current/f18/config-powerpc64p7 @@ -158,7 +158,10 @@ CONFIG_HW_RANDOM_AMD=m CONFIG_UIO_PDRV=m CONFIG_HW_RANDOM_PSERIES=m -CONFIG_CRYPTO_DEV_NX=m +CONFIG_CRYPTO_DEV_NX=y +CONFIG_CRYPTO_842=m +CONFIG_CRYPTO_DEV_NX_ENCRYPT=m +CONFIG_CRYPTO_DEV_NX_COMPRESS=m CONFIG_BPF_JIT=y diff --git a/freed-ora/current/f18/config-s390x b/freed-ora/current/f18/config-s390x index 451512e9a..41e41c53c 100644 --- a/freed-ora/current/f18/config-s390x +++ b/freed-ora/current/f18/config-s390x @@ -241,3 +241,12 @@ CONFIG_STRICT_DEVMEM=y CONFIG_CRYPTO_GHASH_S390=m CONFIG_NET_CORE=y CONFIG_ETHERNET=y + +CONFIG_BPF_JIT=y +# CONFIG_TRANSPARENT_HUGEPAGE is not set +# CONFIG_SCM_BUS is not set +# CONFIG_EADM_SCH is not set +# CONFIG_SCM_BLOCK is not set +# CONFIG_SCM_BLOCK_CLUSTER_WRITE is not set +# CONFIG_S390_PTDUMP is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set diff --git a/freed-ora/current/f18/config-sparc64-generic b/freed-ora/current/f18/config-sparc64-generic index ebc891d8a..e15e2ef18 100644 --- a/freed-ora/current/f18/config-sparc64-generic +++ b/freed-ora/current/f18/config-sparc64-generic @@ -201,3 +201,17 @@ CONFIG_CRYPTO_DEV_NIAGARA2=y CONFIG_BPF_JIT=y # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_IRQ_DOMAIN_DEBUG is not set + +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_RTC_DRV_SNVS is not set +# CONFIG_CRYPTO_CRC32C_SPARC64 is not set +# CONFIG_CRYPTO_MD5_SPARC64 is not set +# CONFIG_CRYPTO_SHA1_SPARC64 is not set +# CONFIG_CRYPTO_SHA256_SPARC64 is not set +# CONFIG_CRYPTO_SHA512_SPARC64 is not set +# CONFIG_CRYPTO_AES_SPARC64 is not set +# CONFIG_CRYPTO_CAMELLIA_SPARC64 is not set +# CONFIG_CRYPTO_DES_SPARC64 is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set + diff --git a/freed-ora/current/f18/config-x86-32-generic b/freed-ora/current/f18/config-x86-32-generic index b1a04993a..1216d47e6 100644 --- a/freed-ora/current/f18/config-x86-32-generic +++ b/freed-ora/current/f18/config-x86-32-generic @@ -190,6 +190,7 @@ CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m # CONFIG_X86_INTEL_MID is not set CONFIG_MFD_CS5535=m +# CONFIG_MFD_SYSCON is not set # I2O enabled only for 32-bit x86, disabled for PAE kernel CONFIG_I2O=m @@ -211,5 +212,8 @@ CONFIG_I2O_BUS=m # CONFIG_GEOS is not set # CONFIG_NET5501 is not set # CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set # CONFIG_GPIO_SODAVILLE is not set +# CONFIG_GPIO_ADNP is not set # CONFIG_BACKLIGHT_OT200 is not set +# CONFIG_RTC_DRV_SNVS is not set diff --git a/freed-ora/current/f18/config-x86-generic b/freed-ora/current/f18/config-x86-generic index b26f42d9f..2bcd498eb 100644 --- a/freed-ora/current/f18/config-x86-generic +++ b/freed-ora/current/f18/config-x86-generic @@ -91,10 +91,11 @@ CONFIG_ACPI_APEI_MEMORY_FAILURE=y # CONFIG_ACPI_APEI_EINJ is not set CONFIG_ACPI_IPMI=m CONFIG_ACPI_CUSTOM_METHOD=m -CONFIG_ACPI_BGRT=m +CONFIG_ACPI_BGRT=y CONFIG_X86_ACPI_CPUFREQ=y CONFIG_X86_PCC_CPUFREQ=y +CONFIG_X86_ACPI_CPUFREQ_CPB=y CONFIG_X86_POWERNOW_K8=y CONFIG_X86_P4_CLOCKMOD=y # CONFIG_X86_SPEEDSTEP_CENTRINO is not set diff --git a/freed-ora/current/f18/config-x86_64-generic b/freed-ora/current/f18/config-x86_64-generic index 342b8620a..6003f11c0 100644 --- a/freed-ora/current/f18/config-x86_64-generic +++ b/freed-ora/current/f18/config-x86_64-generic @@ -46,6 +46,8 @@ CONFIG_CRYPTO_SHA1_SSSE3=m CONFIG_CRYPTO_BLOWFISH_X86_64=m CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=m CONFIG_CRYPTO_CAMELLIA_X86_64=m +CONFIG_CRYPTO_CAST5_AVX_X86_64=m +CONFIG_CRYPTO_CAST6_AVX_X86_64=m CONFIG_CRYPTO_SERPENT_AVX_X86_64=m CONFIG_CRYPTO_TWOFISH_AVX_X86_64=m @@ -107,6 +109,7 @@ CONFIG_X86_X2APIC=y CONFIG_SPARSE_IRQ=y CONFIG_RCU_FANOUT=64 +# CONFIG_RCU_USER_QS is not set CONFIG_INTEL_TXT=y diff --git a/freed-ora/current/f18/deblob-3.6 b/freed-ora/current/f18/deblob-3.7 index 1c6f38230..cfe46d94b 100755 --- a/freed-ora/current/f18/deblob-3.6 +++ b/freed-ora/current/f18/deblob-3.7 @@ -48,7 +48,7 @@ # For each kver release, start extra with an empty string, then count # from 1 if changes are needed that require rebuilding the tarball. -kver=3.6 extra= +kver=3.7 extra= case $1 in --force) @@ -80,6 +80,7 @@ if [ ! -f $check ] ; then have_check=false else have_check=: + [ -x $check ] || check="/bin/sh $check" fi filetest () { @@ -116,7 +117,13 @@ clean_blob () { name=$1 set fnord "$@" -d shift 2 - $check "$@" -i linux-$kver $name > $name.deblob + if $check "$@" -i linux-$kver $name > $name.deblob; then + if [ ! -s $name.deblob ]; then + die got an empty file after removing blobs from $name + fi + else + die failed removing blobs from $name + fi check_changed $name && echo $name: removed blobs else clean_file $1 @@ -208,7 +215,7 @@ maybe_reject_firmware () { #$1 = file $2 = pre sed pattern filetest $1 || return clean_sed "$2"' -s,request_firmware\(_nowait\)\?,maybe_reject_firmware\1,g +s,request_\(ihex_\)\?firmware\(_nowait\)\?,maybe_reject_\1firmware\2,g ' "$1" 'retain Free firmware-loading machinery, disabling non-Free one' } @@ -238,34 +245,40 @@ undefault_firmware () { # corresponding sources are present. for f in \ - drivers/char/ser_a2232fw.h \ - drivers/char/ser_a2232fw.ax \ - drivers/gpu/drm/nouveau/nva3_copy.fuc.h \ - drivers/gpu/drm/nouveau/nva3_copy.fuc \ - drivers/gpu/drm/nouveau/nvc0_copy.fuc.h \ - drivers/gpu/drm/nouveau/nva3_copy.fuc \ - drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h \ - drivers/gpu/drm/nouveau/nvc0_grgpc.fuc \ - drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h \ - drivers/gpu/drm/nouveau/nvc0_grhub.fuc \ - drivers/net/ixp2000/ixp2400_rx.ucode \ - drivers/net/ixp2000/ixp2400_rx.uc \ - drivers/net/ixp2000/ixp2400_tx.ucode \ - drivers/net/ixp2000/ixp2400_rx.uc \ + drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h \ + drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc \ + drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h \ + drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc \ + drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h \ + drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/nvc0.fuc \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/nve0.fuc \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/nvc0.fuc \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h \ + drivers/gpu/drm/nouveau/core/engine/graph/fuc/nve0.fuc \ drivers/net/wan/wanxlfw.inc_shipped \ drivers/net/wan/wanxlfw.S \ drivers/net/wireless/atmel.c \ drivers/net/wireless/atmel.c \ - drivers/scsi/53c700_d.h_shipped \ - drivers/scsi/53c700.scr \ drivers/scsi/aic7xxx/aic79xx_seq.h_shipped \ drivers/scsi/aic7xxx/aic79xx.seq \ drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped \ drivers/scsi/aic7xxx/aic7xxx.seq \ drivers/scsi/aic7xxx_old/aic7xxx_seq.c \ drivers/scsi/aic7xxx_old/aic7xxx.seq \ - drivers/scsi/53c7xx_d.h_shipped \ - drivers/scsi/53c7xx.scr \ + drivers/scsi/53c700_d.h_shipped \ + drivers/scsi/53c700.scr \ drivers/scsi/sym53c8xx_2/sym_fw1.h \ drivers/scsi/sym53c8xx_2/sym_fw1.h \ drivers/scsi/sym53c8xx_2/sym_fw2.h \ @@ -278,12 +291,8 @@ for f in \ firmware/keyspan_pda/xircom_pgs.S \ sound/pci/cs46xx/imgs/cwcdma.h \ sound/pci/cs46xx/imgs/cwcdma.asp \ - firmware/isci/isci_firmware.bin.ihex \ - drivers/scsi/isci/firmware/create_fw.c \ ; do - if test ! $f; then - die $f is not present, something is amiss && return - fi + filetest $f done # Identify the tarball. @@ -407,6 +416,24 @@ maybe_reject_firmware_nowait(struct module *module, int uevent,\ #endif /* _LINUX_LIBRE_FIRMWARE_H */\ ' include/linux/firmware.h 'added non-Free firmware notification support' +grep -q _LINUX_LIBRE_IHEX_FIRMWARE_H include/linux/ihex.h || +clean_sed '$i\ +#ifndef _LINUX_LIBRE_IHEX_H\ +#define _LINUX_LIBRE_IHEX_H\ +\ +static inline int\ +maybe_reject_ihex_firmware(const struct firmware **fw,\ + const char *name, struct device *device)\ +{\ + if (strstr (name, NONFREE_FIRMWARE))\ + return reject_firmware(fw, name, device);\ + else\ + return request_ihex_firmware(fw, name, device);\ +}\ +\ +#endif /* _LINUX_LIBRE_IHEX_H */\ +' include/linux/ihex.h 'added non-Free ihex firmware notification support' + ######## # Arch # ######## @@ -429,7 +456,10 @@ clean_mk CONFIG_MICROCODE_INTEL arch/x86/kernel/Makefile announce IXP4XX_NPE - "IXP4xx Network Processor Engine support" reject_firmware arch/arm/mach-ixp4xx/ixp4xx_npe.c +clean_blob arch/arm/mach-ixp4xx/ixp4xx_npe.c clean_blob Documentation/arm/IXP4xx +clean_kconfig arch/arm/mach-ixp4xx/Kconfig 'ARCH_IXP4XX' +clean_mk CONFIG_IXP4XX_NPE arch/arm/mach-ixp4xx/Makefile announce ARCH_NETX - "Hilscher NetX based" clean_sed ' @@ -470,9 +500,6 @@ clean_mk CONFIG_ATM_SOLOS drivers/atm/Makefile # tty # ######## -announce COMPUTONE - "Computone IntelliPort Plus serial" -drop_fw_file firmware/intelliport2.bin.ihex firmware/intelliport2.bin - announce CYCLADES - "Cyclades async mux support" reject_firmware drivers/tty/cyclades.c clean_blob drivers/tty/cyclades.c @@ -494,10 +521,8 @@ clean_mk CONFIG_MOXA_INTELLIO drivers/tty/Makefile # gpu drm announce DRM_NOUVEAU - "Nouveau (nVidia) cards" -reject_firmware drivers/gpu/drm/nouveau/nvc0_graph.c -clean_blob drivers/gpu/drm/nouveau/nvc0_graph.c -reject_firmware drivers/gpu/drm/nouveau/nve0_graph.c -clean_blob drivers/gpu/drm/nouveau/nve0_graph.c +reject_firmware drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +clean_blob drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c clean_kconfig drivers/gpu/drm/nouveau/Kconfig 'DRM_NOUVEAU' clean_mk CONFIG_DRM_NOUVEAU drivers/gpu/drm/nouveau/Makefile @@ -568,11 +593,9 @@ reject_firmware drivers/dma/imx-sdma.c clean_blob arch/arm/mach-imx/mm-imx25.c clean_blob arch/arm/mach-imx/mm-imx3.c clean_blob arch/arm/mach-imx/mm-imx5.c -clean_blob arch/arm/boot/dts/imx51-babbage.dts -clean_blob arch/arm/boot/dts/imx53-ard.dts -clean_blob arch/arm/boot/dts/imx53-evk.dts -clean_blob arch/arm/boot/dts/imx53-qsb.dts -clean_blob arch/arm/boot/dts/imx53-smd.dts +clean_blob arch/arm/boot/dts/imx51.dtsi +clean_blob arch/arm/boot/dts/imx53.dtsi +clean_blob arch/arm/boot/dts/imx6q.dtsi clean_blob Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt clean_kconfig drivers/dma/Kconfig 'IMX_SDMA' clean_mk CONFIG_IMX_SDMA drivers/dma/Makefile @@ -585,292 +608,299 @@ clean_mk CONFIG_IMX_SDMA drivers/dma/Makefile announce MEDIA_TUNER_XC2028 - "XCeive xc2028/xc3028 tuners" undefault_firmware 'XC\(2028\|3028L\)' \ - drivers/media/common/tuners/tuner-xc2028.h \ - drivers/media/video/saa7134/saa7134-cards.c \ - drivers/media/video/ivtv/ivtv-driver.c \ - drivers/media/video/cx18/cx18-driver.c \ - drivers/media/video/cx18/cx18-dvb.c \ - drivers/media/video/cx23885/cx23885-dvb.c \ - drivers/media/video/cx23885/cx23885-video.c \ - drivers/media/video/cx88/cx88-dvb.c \ - drivers/media/video/cx88/cx88-cards.c \ - drivers/media/video/em28xx/em28xx-cards.c \ - drivers/media/dvb/dvb-usb/dib0700_devices.c \ - drivers/media/dvb/dvb-usb/cxusb.c -reject_firmware drivers/media/common/tuners/tuner-xc2028.c -clean_blob drivers/media/common/tuners/tuner-xc2028.c -clean_kconfig drivers/media/common/tuners/Kconfig 'MEDIA_TUNER_XC2028' -clean_mk CONFIG_MEDIA_TUNER_XC2028 drivers/media/common/tuners/Makefile + drivers/media/tuners/tuner-xc2028.h \ + drivers/media/pci/saa7134/saa7134-cards.c \ + drivers/media/pci/ivtv/ivtv-driver.c \ + drivers/media/pci/cx18/cx18-driver.c \ + drivers/media/pci/cx18/cx18-dvb.c \ + drivers/media/pci/cx23885/cx23885-dvb.c \ + drivers/media/pci/cx23885/cx23885-video.c \ + drivers/media/pci/cx88/cx88-dvb.c \ + drivers/media/pci/cx88/cx88-cards.c \ + drivers/media/usb/em28xx/em28xx-cards.c \ + drivers/media/usb/dvb-usb/dib0700_devices.c \ + drivers/media/usb/dvb-usb/cxusb.c +reject_firmware drivers/media/tuners/tuner-xc2028.c +clean_blob drivers/media/tuners/tuner-xc2028.c +clean_kconfig drivers/media/tuners/Kconfig 'MEDIA_TUNER_XC2028' +clean_mk CONFIG_MEDIA_TUNER_XC2028 drivers/media/tuners/Makefile announce VIDEO_TM6000_DVB - "DVB Support for tm6000 based TV cards" -clean_blob drivers/media/video/tm6000/tm6000-cards.c -clean_kconfig drivers/media/video/tm6000/Kconfig 'VIDEO_TM6000_DVB' -clean_mk CONFIG_VIDEO_TM6000_DVB drivers/media/video/tm6000/Makefile +clean_blob drivers/media/usb/tm6000/tm6000-cards.c +clean_kconfig drivers/media/usb/tm6000/Kconfig 'VIDEO_TM6000_DVB' +clean_mk CONFIG_VIDEO_TM6000_DVB drivers/media/usb/tm6000/Makefile announce MEDIA_TUNER_XC4000 - "Xceive XC4000 silicon tuner" -undefault_firmware 'XC4000' drivers/media/common/tuners/xc4000.c -maybe_reject_firmware drivers/media/common/tuners/xc4000.c -clean_kconfig drivers/media/common/tuners/Kconfig 'MEDIA_TUNER_XC4000' -clean_mk CONFIG_MEDIA_TUNER_XC4000 drivers/media/common/tuners/Makefile +undefault_firmware 'XC4000' drivers/media/tuners/xc4000.c +maybe_reject_firmware drivers/media/tuners/xc4000.c +clean_kconfig drivers/media/tuners/Kconfig 'MEDIA_TUNER_XC4000' +clean_mk CONFIG_MEDIA_TUNER_XC4000 drivers/media/tuners/Makefile announce MEDIA_TUNER_XC5000 - "Xceive XC5000 silicon tuner" undefault_firmware 'XC5000' \ - drivers/media/video/cx231xx/cx231xx-cards.c -reject_firmware drivers/media/common/tuners/xc5000.c -clean_blob drivers/media/common/tuners/xc5000.c -clean_kconfig drivers/media/common/tuners/Kconfig 'MEDIA_TUNER_XC5000' -clean_mk CONFIG_MEDIA_TUNER_XC5000 drivers/media/common/tuners/Makefile + drivers/media/usb/cx231xx/cx231xx-cards.c +reject_firmware drivers/media/tuners/xc5000.c +clean_blob drivers/media/tuners/xc5000.c +clean_kconfig drivers/media/tuners/Kconfig 'MEDIA_TUNER_XC5000' +clean_mk CONFIG_MEDIA_TUNER_XC5000 drivers/media/tuners/Makefile announce DVB_USB - "Support for various USB DVB devices" -reject_firmware drivers/media/dvb/dvb-usb/dvb-usb-firmware.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB' -clean_mk CONFIG_DVB_USB drivers/media/dvb/dvb-usb/Makefile +reject_firmware drivers/media/usb/dvb-usb/dvb-usb-firmware.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB' +clean_mk CONFIG_DVB_USB drivers/media/usb/dvb-usb/Makefile + +announce DVB_USB_V2 - "Support for various USB DVB devices v2" +reject_firmware drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +clean_kconfig drivers/media/usb/dvb-usb-v2/Kconfig 'DVB_USB_V2' +clean_mk CONFIG_DVB_USB_V2 drivers/media/usb/dvb-usb-v2/Makefile announce DVB_B2C2_FLEXCOP - "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters" -reject_firmware drivers/media/dvb/b2c2/flexcop-fe-tuner.c +reject_firmware drivers/media/common/b2c2/flexcop-fe-tuner.c announce DVB_BT8XX - "BT8xx based PCI cards" -reject_firmware drivers/media/dvb/bt8xx/dvb-bt8xx.c +reject_firmware drivers/media/pci/bt8xx/dvb-bt8xx.c announce DVB_USB_A800 - "AVerMedia AverTV DVB-T USB 2.0 (A800)" -clean_blob drivers/media/dvb/dvb-usb/a800.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_A800' -clean_mk CONFIG_DVB_USB_A800 drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb/a800.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_A800' +clean_mk CONFIG_DVB_USB_A800 drivers/media/usb/dvb-usb/Makefile announce DVB_USB_AF9005 - "Afatech AF9005 DVB-T USB1.1 support" -clean_file drivers/media/dvb/dvb-usb/af9005-script.h +clean_file drivers/media/usb/dvb-usb/af9005-script.h clean_sed ' s,^ deb_info("load init script\\n");$, {\n err("Missing Free init script\\n");\n return scriptlen = ret = -EINVAL;\n ,; -' drivers/media/dvb/dvb-usb/af9005-fe.c 'report missing Free init script' -clean_blob drivers/media/dvb/dvb-usb/af9005-fe.c -clean_blob drivers/media/dvb/dvb-usb/af9005.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_AF9005' -clean_mk CONFIG_DVB_USB_AF9005 drivers/media/dvb/dvb-usb/Makefile +' drivers/media/usb/dvb-usb/af9005-fe.c 'report missing Free init script' +clean_blob drivers/media/usb/dvb-usb/af9005-fe.c +clean_blob drivers/media/usb/dvb-usb/af9005.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_AF9005' +clean_mk CONFIG_DVB_USB_AF9005 drivers/media/usb/dvb-usb/Makefile announce DVB_USB_AF9015 - "Afatech AF9015 DVB-T USB2.0 support" -clean_blob drivers/media/dvb/dvb-usb/af9015.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_AF9015' -clean_mk CONFIG_DVB_USB_AF9015 drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb-v2/af9015.h +clean_blob drivers/media/usb/dvb-usb-v2/af9015.c +clean_kconfig drivers/media/usb/dvb-usb-v2/Kconfig 'DVB_USB_AF9015' +clean_mk CONFIG_DVB_USB_AF9015 drivers/media/usb/dvb-usb-v2/Makefile announce DVB_USB_AF9035 - "Afatech AF9035 DVB-T USB2.0 support" -clean_blob drivers/media/dvb/dvb-usb/af9035.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_AF9035' -clean_mk CONFIG_DVB_USB_AF9035 drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb-v2/af9035.h +clean_blob drivers/media/usb/dvb-usb-v2/af9035.c +clean_kconfig drivers/media/usb/dvb-usb-v2/Kconfig 'DVB_USB_AF9035' +clean_mk CONFIG_DVB_USB_AF9035 drivers/media/usb/dvb-usb-v2/Makefile announce DVB_USB_AZ6007 - "Azurewave 6007 and clones DVB-T/C USB2.0 support" -clean_blob drivers/media/dvb/dvb-usb/az6007.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_AZ6007' -clean_mk CONFIG_DVB_USB_AZ6007 drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb-v2/az6007.c +clean_kconfig drivers/media/usb/dvb-usb-v2/Kconfig 'DVB_USB_AZ6007' +clean_mk CONFIG_DVB_USB_AZ6007 drivers/media/usb/dvb-usb-v2/Makefile announce DVB_USB_AZ6027 - "Azurewave DVB-S/S2 USB2.0 AZ6027 support" -clean_blob drivers/media/dvb/dvb-usb/az6027.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_AZ6027' -clean_mk CONFIG_DVB_USB_AZ6027 drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb/az6027.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_AZ6027' +clean_mk CONFIG_DVB_USB_AZ6027 drivers/media/usb/dvb-usb/Makefile announce DVB_USB_CXUSB - "Conexant USB2.0 hybrid reference design support" -clean_blob drivers/media/dvb/dvb-usb/cxusb.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_CXUSB' -clean_mk CONFIG_DVB_USB_CXUSB drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb/cxusb.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_CXUSB' +clean_mk CONFIG_DVB_USB_CXUSB drivers/media/usb/dvb-usb/Makefile announce DVB_USB_DIB0700 - "DiBcom DiB0700 USB DVB devices" -reject_firmware drivers/media/dvb/dvb-usb/dib0700_devices.c -clean_blob drivers/media/dvb/dvb-usb/dib0700_devices.c -clean_blob drivers/media/dvb/dvb-usb/dib0700_core.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_DIB0700' -clean_mk CONFIG_DVB_USB_DIB0700 drivers/media/dvb/dvb-usb/Makefile +reject_firmware drivers/media/usb/dvb-usb/dib0700_devices.c +clean_blob drivers/media/usb/dvb-usb/dib0700_devices.c +clean_blob drivers/media/usb/dvb-usb/dib0700_core.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_DIB0700' +clean_mk CONFIG_DVB_USB_DIB0700 drivers/media/usb/dvb-usb/Makefile announce DVB_USB_DIBUSB_MB - "DiBcom USB DVB-T devices (based on the DiB3000M-B)" -clean_blob drivers/media/dvb/dvb-usb/dibusb-mb.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_DIBUSB_MB' -clean_mk CONFIG_DVB_USB_DIBUSB_MB drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb/dibusb-mb.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_DIBUSB_MB' +clean_mk CONFIG_DVB_USB_DIBUSB_MB drivers/media/usb/dvb-usb/Makefile announce DVB_USB_DIBUSB_MC - "DiBcom USB DVB-T devices (based on the DiB3000M-C/P)" -clean_blob drivers/media/dvb/dvb-usb/dibusb-mc.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_DIBUSB_MC' -clean_mk CONFIG_DVB_USB_DIBUSB_MC drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb/dibusb-mc.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_DIBUSB_MC' +clean_mk CONFIG_DVB_USB_DIBUSB_MC drivers/media/usb/dvb-usb/Makefile announce DVB_USB_DIGITV - "Nebula Electronics uDigiTV DVB-T USB2.0 support" -clean_blob drivers/media/dvb/dvb-usb/digitv.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_DIGITV' -clean_mk CONFIG_DVB_USB_DIGITV drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb/digitv.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_DIGITV' +clean_mk CONFIG_DVB_USB_DIGITV drivers/media/usb/dvb-usb/Makefile announce DVB_USB_DTT200U - "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)" -clean_blob drivers/media/dvb/dvb-usb/dtt200u.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_DTT200U' -clean_mk CONFIG_DVB_USB_DTT200U drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb/dtt200u.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_DTT200U' +clean_mk CONFIG_DVB_USB_DTT200U drivers/media/usb/dvb-usb/Makefile announce DVB_USB_DW2102 - "DvbWorld DVB-S/S2 USB2.0 support" -reject_firmware drivers/media/dvb/dvb-usb/dw2102.c -clean_blob drivers/media/dvb/dvb-usb/dw2102.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_DW2102' -clean_mk CONFIG_DVB_USB_DW2102 drivers/media/dvb/dvb-usb/Makefile +reject_firmware drivers/media/usb/dvb-usb/dw2102.c +clean_blob drivers/media/usb/dvb-usb/dw2102.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_DW2102' +clean_mk CONFIG_DVB_USB_DW2102 drivers/media/usb/dvb-usb/Makefile announce DVB_USB_EC168 - "E3C EC168 DVB-T USB2.0 support" -clean_blob drivers/media/dvb/dvb-usb/ec168.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_EC168' -clean_mk CONFIG_DVB_USB_EC168 drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb-v2/ec168.h +clean_blob drivers/media/usb/dvb-usb-v2/ec168.c +clean_kconfig drivers/media/usb/dvb-usb-v2/Kconfig 'DVB_USB_EC168' +clean_mk CONFIG_DVB_USB_EC168 drivers/media/usb/dvb-usb-v2/Makefile announce DVB_USB_GP8PSK - "GENPIX 8PSK->USB module support" -reject_firmware drivers/media/dvb/dvb-usb/gp8psk.c -clean_blob drivers/media/dvb/dvb-usb/gp8psk.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_GP8PSK' -clean_mk CONFIG_DVB_USB_GP8PSK drivers/media/dvb/dvb-usb/Makefile +reject_firmware drivers/media/usb/dvb-usb/gp8psk.c +clean_blob drivers/media/usb/dvb-usb/gp8psk.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_GP8PSK' +clean_mk CONFIG_DVB_USB_GP8PSK drivers/media/usb/dvb-usb/Makefile announce DVB_USB_IT913X - "it913x driver" -clean_blob drivers/media/dvb/dvb-usb/it913x.c +clean_blob drivers/media/usb/dvb-usb-v2/it913x.c clean_file Documentation/dvb/it9137.txt -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_IT913X' -clean_mk CONFIG_DVB_USB_IT913X drivers/media/dvb/dvb-usb/Makefile +clean_kconfig drivers/media/usb/dvb-usb-v2/Kconfig 'DVB_USB_IT913X' +clean_mk CONFIG_DVB_USB_IT913X drivers/media/usb/dvb-usb-v2/Makefile announce DVB_USB_LME2510 - "LME DM04/QQBOX DVB-S USB2.0 support" -reject_firmware drivers/media/dvb/dvb-usb/lmedm04.c -clean_blob drivers/media/dvb/dvb-usb/lmedm04.c +reject_firmware drivers/media/usb/dvb-usb-v2/lmedm04.c +clean_blob drivers/media/usb/dvb-usb-v2/lmedm04.c clean_file Documentation/dvb/lmedm04.txt -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_LME2510' -clean_mk CONFIG_DVB_USB_LME2510 drivers/media/dvb/dvb-usb/Makefile +clean_kconfig drivers/media/usb/dvb-usb-v2/Kconfig 'DVB_USB_LME2510' +clean_mk CONFIG_DVB_USB_LME2510 drivers/media/usb/dvb-usb-v2/Makefile announce DVB_USB_M920X - "Uli m920x DVB-T USB2.0 support" -reject_firmware drivers/media/dvb/dvb-usb/m920x.c -clean_blob drivers/media/dvb/dvb-usb/m920x.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_M920X' -clean_mk CONFIG_DVB_USB_M920X drivers/media/dvb/dvb-usb/Makefile +reject_firmware drivers/media/usb/dvb-usb/m920x.c +clean_blob drivers/media/usb/dvb-usb/m920x.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_M920X' +clean_mk CONFIG_DVB_USB_M920X drivers/media/usb/dvb-usb/Makefile announce DVB_USB_NOVA_T_USB2 - "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" -clean_blob drivers/media/dvb/dvb-usb/nova-t-usb2.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_NOVA_T_USB2' -clean_mk CONFIG_DVB_USB_NOVA_T_USB2 drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb/nova-t-usb2.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_NOVA_T_USB2' +clean_mk CONFIG_DVB_USB_NOVA_T_USB2 drivers/media/usb/dvb-usb/Makefile announce DVB_USB_OPERA1 - "Opera1 DVB-S USB2.0 receiver" -reject_firmware drivers/media/dvb/dvb-usb/opera1.c -clean_blob drivers/media/dvb/dvb-usb/opera1.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_OPERA1' -clean_mk CONFIG_DVB_USB_OPERA1 drivers/media/dvb/dvb-usb/Makefile +reject_firmware drivers/media/usb/dvb-usb/opera1.c +clean_blob drivers/media/usb/dvb-usb/opera1.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_OPERA1' +clean_mk CONFIG_DVB_USB_OPERA1 drivers/media/usb/dvb-usb/Makefile announce DVB_USB_TECHNISAT_USB2 - "Technisat DVB-S/S2 USB2.0 support" -clean_blob drivers/media/dvb/dvb-usb/technisat-usb2.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_TECHNISAT_USB2' -clean_mk CONFIG_DVB_USB_TECHNISAT_USB2 drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb/technisat-usb2.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_TECHNISAT_USB2' +clean_mk CONFIG_DVB_USB_TECHNISAT_USB2 drivers/media/usb/dvb-usb/Makefile announce DVB_USB_TTUSB2 - "Pinnacle 400e DVB-S USB2.0 support" -clean_blob drivers/media/dvb/dvb-usb/ttusb2.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_TTUSB2' -clean_mk CONFIG_DVB_USB_TTUSB2 drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb/ttusb2.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_TTUSB2' +clean_mk CONFIG_DVB_USB_TTUSB2 drivers/media/usb/dvb-usb/Makefile announce DVB_USB_UMT_010 - "HanfTek UMT-010 DVB-T USB2.0 support" -clean_blob drivers/media/dvb/dvb-usb/umt-010.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_UMT_010' -clean_mk CONFIG_DVB_USB_UMT_010 drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb/umt-010.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_UMT_010' +clean_mk CONFIG_DVB_USB_UMT_010 drivers/media/usb/dvb-usb/Makefile announce DVB_USB_VP702X - "TwinhanDTV StarBox and clones DVB-S USB2.0 support" -clean_blob drivers/media/dvb/dvb-usb/vp702x.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_VP702X' -clean_mk CONFIG_DVB_USB_VP702X drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb/vp702x.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_VP702X' +clean_mk CONFIG_DVB_USB_VP702X drivers/media/usb/dvb-usb/Makefile announce DVB_USB_VP7045 - "TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle USB2.0 support" -clean_blob drivers/media/dvb/dvb-usb/vp7045.c -clean_kconfig drivers/media/dvb/dvb-usb/Kconfig 'DVB_USB_VP7045' -clean_mk CONFIG_DVB_USB_VP7045 drivers/media/dvb/dvb-usb/Makefile +clean_blob drivers/media/usb/dvb-usb/vp7045.c +clean_kconfig drivers/media/usb/dvb-usb/Kconfig 'DVB_USB_VP7045' +clean_mk CONFIG_DVB_USB_VP7045 drivers/media/usb/dvb-usb/Makefile # dvb/frontends announce DVB_AF9013 - "Afatech AF9013 demodulator" -undefault_firmware 'AF9013' \ - drivers/media/dvb/frontends/af9013.c \ - drivers/media/dvb/frontends/af9013_priv.h -reject_firmware drivers/media/dvb/frontends/af9013.c -clean_kconfig drivers/media/dvb/frontends/Kconfig 'DVB_AF9013' -clean_mk CONFIG_DVB_AF9013 drivers/media/dvb/frontends/Makefile +reject_firmware drivers/media/dvb-frontends/af9013.c +clean_blob drivers/media/dvb-frontends/af9013.c +clean_blob drivers/media/dvb-frontends/af9013_priv.h +clean_kconfig drivers/media/dvb-frontends/Kconfig 'DVB_AF9013' +clean_mk CONFIG_DVB_AF9013 drivers/media/dvb-frontends/Makefile announce DVB_BCM3510 - "Broadcom BCM3510" -undefault_firmware 'BCM3510' drivers/media/dvb/frontends/bcm3510.c -reject_firmware drivers/media/dvb/frontends/bcm3510.c -reject_firmware drivers/media/dvb/frontends/bcm3510.h +undefault_firmware 'BCM3510' drivers/media/dvb-frontends/bcm3510.c +reject_firmware drivers/media/dvb-frontends/bcm3510.c +reject_firmware drivers/media/dvb-frontends/bcm3510.h clean_sed ' /You.ll need a firmware/,/dvb-fe-bcm/d; -' drivers/media/dvb/frontends/bcm3510.c \ +' drivers/media/dvb-frontends/bcm3510.c \ "removed non-Free firmware notes" -clean_kconfig drivers/media/dvb/frontends/Kconfig 'DVB_BCM3510' -clean_mk CONFIG_DVB_BCM3510 drivers/media/dvb/frontends/Makefile +clean_kconfig drivers/media/dvb-frontends/Kconfig 'DVB_BCM3510' +clean_mk CONFIG_DVB_BCM3510 drivers/media/dvb-frontends/Makefile announce DVB_DS3000 - "Montage Tehnology DS3000 based" undefault_firmware 'DS3000' \ - drivers/media/dvb/frontends/ds3000.c -reject_firmware drivers/media/dvb/frontends/ds3000.c -clean_blob drivers/media/dvb/frontends/ds3000.c -clean_kconfig drivers/media/dvb/frontends/Kconfig 'DVB_DS3000' -clean_mk CONFIG_DVB_DS3000 drivers/media/dvb/frontends/Makefile + drivers/media/dvb-frontends/ds3000.c +reject_firmware drivers/media/dvb-frontends/ds3000.c +clean_blob drivers/media/dvb-frontends/ds3000.c +clean_kconfig drivers/media/dvb-frontends/Kconfig 'DVB_DS3000' +clean_mk CONFIG_DVB_DS3000 drivers/media/dvb-frontends/Makefile announce DVB_LGS8GXX - "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator" -reject_firmware drivers/media/dvb/frontends/lgs8gxx.c -clean_blob drivers/media/dvb/frontends/lgs8gxx.c -clean_kconfig drivers/media/dvb/frontends/Kconfig 'DVB_LGS8GXX' -clean_mk CONFIG_DVB_LGS8GXX drivers/media/dvb/frontends/Makefile +reject_firmware drivers/media/dvb-frontends/lgs8gxx.c +clean_blob drivers/media/dvb-frontends/lgs8gxx.c +clean_kconfig drivers/media/dvb-frontends/Kconfig 'DVB_LGS8GXX' +clean_mk CONFIG_DVB_LGS8GXX drivers/media/dvb-frontends/Makefile announce DVB_NXT200X - "NxtWave Communications NXT2002/NXT2004 based" -undefault_firmware 'NXT200[24]' drivers/media/dvb/frontends/nxt200x.c -reject_firmware drivers/media/dvb/frontends/nxt200x.c -clean_blob drivers/media/dvb/frontends/nxt200x.c -clean_kconfig drivers/media/dvb/frontends/Kconfig 'DVB_NXT200X' -clean_mk CONFIG_DVB_NXT200X drivers/media/dvb/frontends/Makefile +undefault_firmware 'NXT200[24]' drivers/media/dvb-frontends/nxt200x.c +reject_firmware drivers/media/dvb-frontends/nxt200x.c +clean_blob drivers/media/dvb-frontends/nxt200x.c +clean_kconfig drivers/media/dvb-frontends/Kconfig 'DVB_NXT200X' +clean_mk CONFIG_DVB_NXT200X drivers/media/dvb-frontends/Makefile announce DVB_OR51132 - "Oren OR51132 based" -reject_firmware drivers/media/dvb/frontends/or51132.c -clean_blob drivers/media/dvb/frontends/or51132.c -clean_kconfig drivers/media/dvb/frontends/Kconfig 'DVB_OR51132' -clean_mk CONFIG_DVB_OR51132 drivers/media/dvb/frontends/Makefile +reject_firmware drivers/media/dvb-frontends/or51132.c +clean_blob drivers/media/dvb-frontends/or51132.c +clean_kconfig drivers/media/dvb-frontends/Kconfig 'DVB_OR51132' +clean_mk CONFIG_DVB_OR51132 drivers/media/dvb-frontends/Makefile announce DVB_OR51211 - "Oren OR51211 based" -undefault_firmware 'OR51211' drivers/media/dvb/frontends/or51211.c -reject_firmware drivers/media/dvb/frontends/or51211.c -reject_firmware drivers/media/dvb/frontends/or51211.h -clean_blob drivers/media/dvb/frontends/or51211.c -clean_kconfig drivers/media/dvb/frontends/Kconfig 'DVB_OR51211' -clean_mk CONFIG_DVB_OR51211 drivers/media/dvb/frontends/Makefile +undefault_firmware 'OR51211' drivers/media/dvb-frontends/or51211.c +reject_firmware drivers/media/dvb-frontends/or51211.c +reject_firmware drivers/media/dvb-frontends/or51211.h +clean_blob drivers/media/dvb-frontends/or51211.c +clean_kconfig drivers/media/dvb-frontends/Kconfig 'DVB_OR51211' +clean_mk CONFIG_DVB_OR51211 drivers/media/dvb-frontends/Makefile announce DVB_SP8870 - "Spase sp8870" -undefault_firmware 'SP8870' drivers/media/dvb/frontends/sp8870.c -reject_firmware drivers/media/dvb/frontends/sp8870.c -reject_firmware drivers/media/dvb/frontends/sp8870.h -clean_blob drivers/media/dvb/frontends/sp8870.c -clean_kconfig drivers/media/dvb/frontends 'DVB_SP8870' -clean_mk CONFIG_DVB_SP8870 drivers/media/dvb/frontends/Makefile +undefault_firmware 'SP8870' drivers/media/dvb-frontends/sp8870.c +reject_firmware drivers/media/dvb-frontends/sp8870.c +reject_firmware drivers/media/dvb-frontends/sp8870.h +clean_blob drivers/media/dvb-frontends/sp8870.c +clean_kconfig drivers/media/dvb-frontends 'DVB_SP8870' +clean_mk CONFIG_DVB_SP8870 drivers/media/dvb-frontends/Makefile announce DVB_CX24116 - "Conexant CX24116 based" -undefault_firmware CX24116 drivers/media/dvb/frontends/cx24116.c -reject_firmware drivers/media/dvb/frontends/cx24116.c -clean_kconfig drivers/media/dvb/frontends/Kconfig 'DVB_CX24116' -clean_mk CONFIG_DVB_CX24116 drivers/media/dvb/frontends/Makefile +undefault_firmware CX24116 drivers/media/dvb-frontends/cx24116.c +reject_firmware drivers/media/dvb-frontends/cx24116.c +clean_kconfig drivers/media/dvb-frontends/Kconfig 'DVB_CX24116' +clean_mk CONFIG_DVB_CX24116 drivers/media/dvb-frontends/Makefile announce DVB_SP887X - "Spase sp887x based" -undefault_firmware 'SP887X' drivers/media/dvb/frontends/sp887x.c -reject_firmware drivers/media/dvb/frontends/sp887x.c -reject_firmware drivers/media/dvb/frontends/sp887x.h -clean_blob drivers/media/dvb/frontends/sp887x.c -clean_kconfig drivers/media/dvb/frontends/Kconfig 'DVB_SP887X' -clean_mk CONFIG_DVB_SP887X drivers/media/dvb/frontends/Makefile +undefault_firmware 'SP887X' drivers/media/dvb-frontends/sp887x.c +reject_firmware drivers/media/dvb-frontends/sp887x.c +reject_firmware drivers/media/dvb-frontends/sp887x.h +clean_blob drivers/media/dvb-frontends/sp887x.c +clean_kconfig drivers/media/dvb-frontends/Kconfig 'DVB_SP887X' +clean_mk CONFIG_DVB_SP887X drivers/media/dvb-frontends/Makefile announce DVB_TDA10048 - "Philips TDA10048HN based" undefine_macro 'TDA10048_DEFAULT_FIRMWARE_SIZE' 0 \ - 'removed non-Free firmware size' drivers/media/dvb/frontends/tda10048.c -undefault_firmware 'TDA10048' drivers/media/dvb/frontends/tda10048.c -reject_firmware drivers/media/dvb/frontends/tda10048.c -clean_kconfig drivers/media/dvb/frontends/Kconfig 'DVB_TDA10048' -clean_mk CONFIG_DVB_TDA10048 drivers/media/dvb/frontends/Makefile + 'removed non-Free firmware size' drivers/media/dvb-frontends/tda10048.c +undefault_firmware 'TDA10048' drivers/media/dvb-frontends/tda10048.c +reject_firmware drivers/media/dvb-frontends/tda10048.c +clean_kconfig drivers/media/dvb-frontends/Kconfig 'DVB_TDA10048' +clean_mk CONFIG_DVB_TDA10048 drivers/media/dvb-frontends/Makefile announce DVB_TDA1004X - "Philips TDA10045H/TDA10046H" -undefault_firmware 'TDA1004[56]' drivers/media/dvb/frontends/tda1004x.c -reject_firmware drivers/media/dvb/frontends/tda1004x.c -reject_firmware drivers/media/dvb/frontends/tda1004x.h -clean_blob drivers/media/dvb/frontends/tda1004x.c -clean_kconfig drivers/media/dvb/frontends 'DVB_TDA1004X' -clean_mk CONFIG_DVB_TDA1004X drivers/media/dvb/frontends/Makefile +undefault_firmware 'TDA1004[56]' drivers/media/dvb-frontends/tda1004x.c +reject_firmware drivers/media/dvb-frontends/tda1004x.c +reject_firmware drivers/media/dvb-frontends/tda1004x.h +clean_blob drivers/media/dvb-frontends/tda1004x.c +clean_kconfig drivers/media/dvb-frontends 'DVB_TDA1004X' +clean_mk CONFIG_DVB_TDA1004X drivers/media/dvb-frontends/Makefile announce DVB_TDA10071 - "NXP TDA10071" -undefault_firmware 'TDA10071' drivers/media/dvb/frontends/tda10071_priv.h -undefault_firmware 'TDA10071' drivers/media/dvb/frontends/tda10071.c -reject_firmware drivers/media/dvb/frontends/tda10071.c -clean_kconfig drivers/media/dvb/frontends 'DVB_TDA10071' -clean_mk CONFIG_DVB_TDA10071 drivers/media/dvb/frontends/Makefile +reject_firmware drivers/media/dvb-frontends/tda10071.c +clean_blob drivers/media/dvb-frontends/tda10071.c +clean_blob drivers/media/dvb-frontends/tda10071_priv.h +clean_kconfig drivers/media/dvb-frontends 'DVB_TDA10071' +clean_mk CONFIG_DVB_TDA10071 drivers/media/dvb-frontends/Makefile # dvb @@ -881,135 +911,142 @@ clean_kconfig drivers/staging/media/as102/Kconfig 'DVB_AS102' clean_mk CONFIG_DVB_AS102 drivers/staging/media/as102/Makefile announce DVB_AV7110 - "AV7110 cards" -reject_firmware drivers/media/dvb/ttpci/av7110.c -clean_blob drivers/media/dvb/ttpci/av7110.c -clean_kconfig drivers/media/dvb/ttpci/Kconfig 'DVB_AV7110' -clean_mk CONFIG_DVB_AV7110 drivers/media/dvb/ttpci/Makefile +reject_firmware drivers/media/pci/ttpci/av7110.c +clean_blob drivers/media/pci/ttpci/av7110.c +clean_kconfig drivers/media/pci/ttpci/Kconfig 'DVB_AV7110' +clean_mk CONFIG_DVB_AV7110 drivers/media/pci/ttpci/Makefile announce DVB_BUDGET - "Budget cards" -reject_firmware drivers/media/dvb/ttpci/budget.c -reject_firmware drivers/media/dvb/frontends/tdhd1.h +reject_firmware drivers/media/pci/ttpci/budget.c +reject_firmware drivers/media/dvb-frontends/tdhd1.h announce DVB_BUDGET_AV - "Budget cards with analog video inputs" -reject_firmware drivers/media/dvb/ttpci/budget-av.c +reject_firmware drivers/media/pci/ttpci/budget-av.c announce DVB_BUDGET_CI - "Budget cards with onboard CI connector" -reject_firmware drivers/media/dvb/ttpci/budget-ci.c +reject_firmware drivers/media/pci/ttpci/budget-ci.c announce DVB_DRXD - "Micronas DRXD driver" -reject_firmware drivers/media/dvb/frontends/drxd_hard.c -clean_blob drivers/media/dvb/frontends/drxd_hard.c -clean_kconfig drivers/media/dvb/frontends/Kconfig 'DVB_DRXD' -clean_mk CONFIG_DVB_DRXD drivers/media/dvb/frontends/Makefile +reject_firmware drivers/media/dvb-frontends/drxd_hard.c +clean_blob drivers/media/dvb-frontends/drxd_hard.c +clean_kconfig drivers/media/dvb-frontends/Kconfig 'DVB_DRXD' +clean_mk CONFIG_DVB_DRXD drivers/media/dvb-frontends/Makefile announce DVB_DRXK - "Micronas DRXK based" -reject_firmware drivers/media/dvb/frontends/drxk_hard.c -clean_kconfig drivers/media/dvb/frontends/Kconfig 'DVB_DRXK' -clean_mk CONFIG_DVB_DRXK drivers/media/dvb/frontends/Makefile +reject_firmware drivers/media/dvb-frontends/drxk_hard.c +clean_kconfig drivers/media/dvb-frontends/Kconfig 'DVB_DRXK' +clean_mk CONFIG_DVB_DRXK drivers/media/dvb-frontends/Makefile announce DVB_NGENE - "Micronas nGene support" -reject_firmware drivers/media/dvb/ngene/ngene-core.c -clean_blob drivers/media/dvb/ngene/ngene-core.c -clean_kconfig drivers/media/dvb/ngene/Kconfig 'DVB_NGENE' -clean_mk CONFIG_DVB_NGENE drivers/media/dvb/ngene/Makefile +reject_firmware drivers/media/pci/ngene/ngene-core.c +clean_blob drivers/media/pci/ngene/ngene-core.c +clean_kconfig drivers/media/pci/ngene/Kconfig 'DVB_NGENE' +clean_mk CONFIG_DVB_NGENE drivers/media/pci/ngene/Makefile announce DVB_PLUTO2 - "Pluto2 cards" -reject_firmware drivers/media/dvb/pluto2/pluto2.c +reject_firmware drivers/media/pci/pluto2/pluto2.c announce SMS_SIANO_MDTV - "Siano SMS1xxx based MDTV receiver" -reject_firmware drivers/media/dvb/siano/smscoreapi.c -clean_blob drivers/media/dvb/siano/smscoreapi.c -clean_blob drivers/media/dvb/siano/sms-cards.c -clean_kconfig drivers/media/dvb/siano/Kconfig 'SMS_SIANO_MDTV' -clean_mk CONFIG_SMS_SIANO_MDTV drivers/media/dvb/siano/Makefile +reject_firmware drivers/media/common/siano/smscoreapi.c +clean_blob drivers/media/common/siano/smscoreapi.c +clean_blob drivers/media/common/siano/sms-cards.c +clean_kconfig drivers/media/common/siano/Kconfig 'SMS_SIANO_MDTV' +clean_mk CONFIG_SMS_SIANO_MDTV drivers/media/common/siano/Makefile announce SMS_USB_DRV - "Siano's USB interface support" -reject_firmware drivers/media/dvb/siano/smsusb.c -clean_blob drivers/media/dvb/siano/smsusb.c -clean_kconfig drivers/media/dvb/siano/Kconfig 'SMS_USB_DRV' -clean_mk CONFIG_SMS_USB_DRV drivers/media/dvb/siano/Makefile +reject_firmware drivers/media/usb/siano/smsusb.c +clean_blob drivers/media/usb/siano/smsusb.c +clean_kconfig drivers/media/usb/siano/Kconfig 'SMS_USB_DRV' +clean_mk CONFIG_SMS_USB_DRV drivers/media/usb/siano/Makefile announce DVB_TTUSB_BUDGET - "Technotrend/Hauppauge Nova-USB devices" drop_fw_file firmware/ttusb-budget/dspbootcode.bin.ihex firmware/ttusb-budget/dspbootcode.bin -reject_firmware drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c -clean_blob drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c -clean_kconfig drivers/media/dvb/ttusb-budget/Kconfig 'DVB_TTUSB_BUDGET' -clean_mk CONFIG_DVB_TTUSB_BUDGET drivers/media/dvb/ttusb-budget/Makefile +reject_firmware drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c +clean_blob drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c +clean_kconfig drivers/media/usb/ttusb-budget/Kconfig 'DVB_TTUSB_BUDGET' +clean_mk CONFIG_DVB_TTUSB_BUDGET drivers/media/usb/ttusb-budget/Makefile announce DVB_TTUSB_DEC - "Technotrend/Hauppauge USB DEC devices" -reject_firmware drivers/media/dvb/ttusb-dec/ttusb_dec.c -clean_blob drivers/media/dvb/ttusb-dec/ttusb_dec.c +reject_firmware drivers/media/usb/ttusb-dec/ttusb_dec.c +clean_blob drivers/media/usb/ttusb-dec/ttusb_dec.c clean_blob Documentation/dvb/ttusb-dec.txt -clean_kconfig drivers/media/dvb/ttusb-dec/Kconfig 'DVB_TTUSB_DEC' -clean_mk CONFIG_DVB_TTUSB_DEC drivers/media/dvb/ttusb-dec/Makefile +clean_kconfig drivers/media/usb/ttusb-dec/Kconfig 'DVB_TTUSB_DEC' +clean_mk CONFIG_DVB_TTUSB_DEC drivers/media/usb/ttusb-dec/Makefile # video announce VIDEO_BT848 - "BT848 Video For Linux" -reject_firmware drivers/media/video/bt8xx/bttv-cards.c -clean_blob drivers/media/video/bt8xx/bttv-cards.c +reject_firmware drivers/media/pci/bt8xx/bttv-cards.c +clean_blob drivers/media/pci/bt8xx/bttv-cards.c clean_blob Documentation/video4linux/bttv/README -clean_kconfig drivers/media/video/bt8xx/Kconfig 'VIDEO_BT848' -clean_mk CONFIG_VIDEO_BT848 drivers/media/video/bt8xx/Makefile +clean_kconfig drivers/media/pci/bt8xx/Kconfig 'VIDEO_BT848' +clean_mk CONFIG_VIDEO_BT848 drivers/media/pci/bt8xx/Makefile + +announce VIDEO_CODA - "Chips&Media Coda multi-standard codec IP" +reject_firmware drivers/media/platform/coda.c +clean_blob drivers/media/platform/coda.c +clean_kconfig drivers/media/platform/Kconfig 'VIDEO_CODA' +clean_mk CONFIG_VIDEO_CODA drivers/media/platform/Makefile announce VIDEO_CPIA2 - "CPiA2 Video For Linux" clean_fw firmware/cpia2/stv0672_vp4.bin.ihex firmware/cpia2/stv0672_vp4.bin -reject_firmware drivers/media/video/cpia2/cpia2_core.c -clean_blob drivers/media/video/cpia2/cpia2_core.c -clean_kconfig drivers/media/video/cpia2/Kconfig 'VIDEO_CPIA2' -clean_mk CONFIG_VIDEO_CPIA2 drivers/media/video/cpia2/Makefile +reject_firmware drivers/media/usb/cpia2/cpia2_core.c +clean_blob drivers/media/usb/cpia2/cpia2_core.c +clean_kconfig drivers/media/usb/cpia2/Kconfig 'VIDEO_CPIA2' +clean_mk CONFIG_VIDEO_CPIA2 drivers/media/usb/cpia2/Makefile announce VIDEO_CX18 - "Conexant cx23418 MPEG encoder support" -reject_firmware drivers/media/video/cx18/cx18-av-firmware.c -reject_firmware drivers/media/video/cx18/cx18-dvb.c -reject_firmware drivers/media/video/cx18/cx18-firmware.c -clean_blob drivers/media/video/cx18/cx18-av-firmware.c -clean_blob drivers/media/video/cx18/cx18-dvb.c -clean_blob drivers/media/video/cx18/cx18-firmware.c -clean_kconfig drivers/media/video/cx18/Kconfig 'VIDEO_CX18' -clean_mk CONFIG_VIDEO_CX18 drivers/media/video/cx18/Makefile +reject_firmware drivers/media/pci/cx18/cx18-av-firmware.c +reject_firmware drivers/media/pci/cx18/cx18-dvb.c +reject_firmware drivers/media/pci/cx18/cx18-firmware.c +clean_blob drivers/media/pci/cx18/cx18-av-firmware.c +clean_blob drivers/media/pci/cx18/cx18-dvb.c +clean_blob drivers/media/pci/cx18/cx18-firmware.c +clean_blob drivers/media/pci/cx18/cx18-driver.c +clean_kconfig drivers/media/pci/cx18/Kconfig 'VIDEO_CX18' +clean_mk CONFIG_VIDEO_CX18 drivers/media/pci/cx18/Makefile announce VIDEO_CX231XX - "Conexant cx231xx USB video capture support" -reject_firmware drivers/media/video/cx231xx/cx231xx-417.c -clean_blob drivers/media/video/cx231xx/cx231xx-417.c -clean_kconfig drivers/media/video/cx231xx/Kconfig 'VIDEO_CX231XX' -clean_mk CONFIG_VIDEO_CX231XX drivers/media/video/cx231xx/Makefile +reject_firmware drivers/media/usb/cx231xx/cx231xx-417.c +clean_blob drivers/media/usb/cx231xx/cx231xx-417.c +clean_kconfig drivers/media/usb/cx231xx/Kconfig 'VIDEO_CX231XX' +clean_mk CONFIG_VIDEO_CX231XX drivers/media/usb/cx231xx/Makefile announce VIDEO_CX23885 - "Conexant cx23885 (2388x successor) support" -reject_firmware drivers/media/video/cx23885/cx23885-417.c -clean_blob drivers/media/video/cx23885/cx23885-417.c -reject_firmware drivers/media/video/cx23885/cx23885-cards.c -clean_blob drivers/media/video/cx23885/cx23885-cards.c -clean_kconfig drivers/media/video/cx23885/Kconfig 'VIDEO_CX23885' -clean_mk CONFIG_VIDEO_CX23885 drivers/media/video/cx23885/Makefile +reject_firmware drivers/media/pci/cx23885/cx23885-417.c +clean_blob drivers/media/pci/cx23885/cx23885-417.c +reject_firmware drivers/media/pci/cx23885/cx23885-cards.c +clean_blob drivers/media/pci/cx23885/cx23885-cards.c +clean_kconfig drivers/media/pci/cx23885/Kconfig 'VIDEO_CX23885' +clean_mk CONFIG_VIDEO_CX23885 drivers/media/pci/cx23885/Makefile announce VIDEO_CX25840 - "Conexant CX2584x audio/video decoders" -reject_firmware drivers/media/video/cx25840/cx25840-firmware.c -clean_blob drivers/media/video/cx25840/cx25840-firmware.c -clean_kconfig drivers/media/video/cx25840/Kconfig 'VIDEO_CX25840' -clean_mk CONFIG_VIDEO_CX25840 drivers/media/video/cx25840/Makefile +reject_firmware drivers/media/i2c/cx25840/cx25840-firmware.c +clean_blob drivers/media/i2c/cx25840/cx25840-firmware.c +clean_kconfig drivers/media/i2c/cx25840/Kconfig 'VIDEO_CX25840' +clean_mk CONFIG_VIDEO_CX25840 drivers/media/i2c/cx25840/Makefile announce VIDEO_CX88_BLACKBIRD - "Blackbird MPEG encoder support (cx2388x + cx23416)" -reject_firmware drivers/media/video/cx88/cx88-blackbird.c -clean_kconfig drivers/media/video/cx88/Kconfig 'VIDEO_CX88_BLACKBIRD' -clean_mk CONFIG_VIDEO_CX88_BLACKBIRD drivers/media/video/cx88/Makefile +reject_firmware drivers/media/pci/cx88/cx88-blackbird.c +clean_kconfig drivers/media/pci/cx88/Kconfig 'VIDEO_CX88_BLACKBIRD' +clean_mk CONFIG_VIDEO_CX88_BLACKBIRD drivers/media/pci/cx88/Makefile announce VIDEO_EM28XX_DVB - "DVB/ATSC Support for em28xx based TV cards" -clean_blob drivers/media/video/em28xx/em28xx-dvb.c -clean_kconfig drivers/media/video/em28xx/Kconfig 'VIDEO_EM28XX_DVB' -clean_mk CONFIG_VIDEO_EM28XX_DVB drivers/media/video/em28xx/Makefile +clean_blob drivers/media/usb/em28xx/em28xx-dvb.c +clean_kconfig drivers/media/usb/em28xx/Kconfig 'VIDEO_EM28XX_DVB' +clean_mk CONFIG_VIDEO_EM28XX_DVB drivers/media/usb/em28xx/Makefile announce VIDEO_IVTV - "Conexant cx23416/cx23415 MPEG encoder/decoder support" -reject_firmware drivers/media/video/ivtv/ivtv-firmware.c -clean_blob drivers/media/video/ivtv/ivtv-firmware.c -clean_kconfig drivers/media/video/ivtv/Kconfig 'VIDEO_IVTV' -clean_mk CONFIG_VIDEO_IVTV drivers/media/video/ivtv/Makefile +reject_firmware drivers/media/pci/ivtv/ivtv-firmware.c +clean_blob drivers/media/pci/ivtv/ivtv-firmware.c +clean_kconfig drivers/media/pci/ivtv/Kconfig 'VIDEO_IVTV' +clean_mk CONFIG_VIDEO_IVTV drivers/media/pci/ivtv/Makefile announce VIDEO_PVRUSB2 - "Hauppauge WinTV-PVR USB2 support" -reject_firmware drivers/media/video/pvrusb2/pvrusb2-hdw.c -clean_blob drivers/media/video/pvrusb2/pvrusb2-devattr.c -clean_kconfig drivers/media/video/pvrusb2/Kconfig 'VIDEO_PVRUSB2' -clean_mk CONFIG_VIDEO_PVRUSB2 drivers/media/video/pvrusb2/Makefile +reject_firmware drivers/media/usb/pvrusb2/pvrusb2-hdw.c +clean_blob drivers/media/usb/pvrusb2/pvrusb2-devattr.c +clean_kconfig drivers/media/usb/pvrusb2/Kconfig 'VIDEO_PVRUSB2' +clean_mk CONFIG_VIDEO_PVRUSB2 drivers/media/usb/pvrusb2/Makefile announce "VIDEO_CX23885, VIDEO_CX88_BLACKBIRD, VIDEO_IVTV, VIDEO_PVRUSB2" - "See above" clean_blob include/media/cx2341x.h @@ -1030,44 +1067,50 @@ clean_kconfig drivers/staging/media/go7007/Kconfig 'VIDEO_GO7007_USB_S2250_BOARD clean_mk CONFIG_VIDEO_GO7007_USB_S2250_BOARD drivers/staging/media/go7007/Makefile announce VIDEO_SAA7134_DVB - "DVB/ATSC Support for saa7134 based TV cards" -reject_firmware drivers/media/video/saa7134/saa7134-dvb.c -clean_kconfig drivers/media/video/saa7134/Kconfig 'VIDEO_SAA7134_DVB' -clean_mk CONFIG_VIDEO_SAA7134_DVB drivers/media/video/saa7134/Makefile +reject_firmware drivers/media/pci/saa7134/saa7134-dvb.c +clean_kconfig drivers/media/pci/saa7134/Kconfig 'VIDEO_SAA7134_DVB' +clean_mk CONFIG_VIDEO_SAA7134_DVB drivers/media/pci/saa7134/Makefile announce VIDEO_SAA7164 - "NXP SAA7164 support" -reject_firmware drivers/media/video/saa7164/saa7164-fw.c -clean_blob drivers/media/video/saa7164/saa7164-fw.c -clean_kconfig drivers/media/video/saa7164/Kconfig 'VIDEO_SAA7164' -clean_mk CONFIG_VIDEO_SAA7164 drivers/media/video/saa7164/Makefile +reject_firmware drivers/media/pci/saa7164/saa7164-fw.c +clean_blob drivers/media/pci/saa7164/saa7164-fw.c +clean_kconfig drivers/media/pci/saa7164/Kconfig 'VIDEO_SAA7164' +clean_mk CONFIG_VIDEO_SAA7164 drivers/media/pci/saa7164/Makefile announce VIDEO_TLG2300 - "Telegent TLG2300 USB video capture support" -reject_firmware drivers/media/video/tlg2300/pd-main.c -clean_blob drivers/media/video/tlg2300/pd-main.c -clean_kconfig drivers/media/video/tlg2300/Kconfig 'VIDEO_TLG2300' -clean_mk CONFIG_VIDEO_TLG2300 drivers/media/video/tlg2300/Makefile +reject_firmware drivers/media/usb/tlg2300/pd-main.c +clean_blob drivers/media/usb/tlg2300/pd-main.c +clean_kconfig drivers/media/usb/tlg2300/Kconfig 'VIDEO_TLG2300' +clean_mk CONFIG_VIDEO_TLG2300 drivers/media/usb/tlg2300/Makefile + +announce VIDEO_S5K4ECGX - "Samsung S5K4ECGX sensor support" +reject_firmware drivers/media/i2c/s5k4ecgx.c +clean_blob drivers/media/i2c/s5k4ecgx.c +clean_kconfig drivers/media/i2c/s5k4ecgx.c 'VIDEO_S5K4ECGX' +clean_mk CONFIG_VIDEO_S5K4ECGX drivers/media/i2c/Makefile announce VIDEO_SAMSUNG_S5P_MFC - "Samsung S5P MFC 5.1 Video Codec" -reject_firmware drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c -clean_blob drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c -clean_kconfig drivers/media/video/Kconfig 'VIDEO_SAMSUNG_S5P_MFC' -clean_mk CONFIG_VIDEO_SAMSUNG_S5P_MFC drivers/media/video/s5p-mfc/Makefile +reject_firmware drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +clean_blob drivers/media/platform/s5p-mfc/s5p_mfc.c +clean_kconfig drivers/media/platform/Kconfig 'VIDEO_SAMSUNG_S5P_MFC' +clean_mk CONFIG_VIDEO_SAMSUNG_S5P_MFC drivers/media/platform/s5p-mfc/Makefile announce USB_DABUSB - "left-over DABUSB firmware" clean_fw firmware/dabusb/bitstream.bin.ihex firmware/dabusb/bitstream.bin clean_fw firmware/dabusb/firmware.HEX firmware/dabusb/firmware.fw announce USB_S2255 - "USB Sensoray 2255 video capture device" -reject_firmware drivers/media/video/s2255drv.c -clean_blob drivers/media/video/s2255drv.c -clean_kconfig drivers/media/video/Kconfig 'USB_S2255' -clean_mk CONFIG_USB_S2255 drivers/media/video/Makefile +reject_firmware drivers/media/usb/s2255/s2255drv.c +clean_blob drivers/media/usb/s2255/s2255drv.c +clean_kconfig drivers/media/usb/Kconfig 'USB_S2255' +clean_mk CONFIG_USB_S2255 drivers/media/usb/s2255/Makefile announce USB_GSPCA_VICAM - "USB 3com HomeConnect, AKA vicam" drop_fw_file firmware/vicam/firmware.H16 firmware/vicam/firmware.fw -reject_firmware drivers/media/video/gspca/vicam.c -clean_blob drivers/media/video/gspca/vicam.c -clean_kconfig drivers/media/video/gspca/Kconfig 'USB_GSPCA_VICAM' -clean_mk CONFIG_USB_GSPCA_VICAM drivers/media/video/gspca/Makefile +reject_firmware drivers/media/usb/gspca/vicam.c +clean_blob drivers/media/usb/gspca/vicam.c +clean_kconfig drivers/media/usb/gspca/Kconfig 'USB_GSPCA_VICAM' +clean_mk CONFIG_USB_GSPCA_VICAM drivers/media/usb/gspca/Makefile # radio @@ -1167,7 +1210,6 @@ clean_mk CONFIG_CASSINI drivers/net/ethernet/sun/Makefile announce CHELSIO_T3 - "Chelsio AEL 2005 support" drop_fw_file firmware/cxgb3/t3b_psram-1.1.0.bin.ihex firmware/cxgb3/t3b_psram-1.1.0.bin drop_fw_file firmware/cxgb3/t3c_psram-1.1.0.bin.ihex firmware/cxgb3/t3c_psram-1.1.0.bin -drop_fw_file firmware/cxgb3/t3fw-7.10.0.bin.ihex firmware/cxgb3/t3fw-7.10.0.bin drop_fw_file firmware/cxgb3/ael2005_opt_edc.bin.ihex firmware/cxgb3/ael2005_opt_edc.bin drop_fw_file firmware/cxgb3/ael2005_twx_edc.bin.ihex firmware/cxgb3/ael2005_twx_edc.bin drop_fw_file firmware/cxgb3/ael2020_twx_edc.bin.ihex firmware/cxgb3/ael2020_twx_edc.bin @@ -1705,8 +1747,10 @@ clean_mk CONFIG_RTL8192SE drivers/net/wireless/rtlwifi/rtl8192se/Makefile announce RTL8192E - "RealTek RTL8192E Wireless LAN NIC driver" reject_firmware drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c +clean_blob drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h clean_blob drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c clean_blob drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c +clean_blob drivers/staging/rtl8192e/rtl8192e/rtl_core.c clean_kconfig drivers/staging/rtl8192e/Kconfig RTL8192E clean_mk CONFIG_RTL8192E drivers/staging/rtl8192e/Makefile @@ -1748,6 +1792,7 @@ clean_mk CONFIG_WL18XX drivers/net/wireless/ti/wl18xx/Makefile announce WLCORE - "TI wlcore support" reject_firmware drivers/net/wireless/ti/wlcore/main.c +clean_blob drivers/net/wireless/ti/wlcore/main.c clean_blob drivers/net/wireless/ti/wlcore/wlcore_i.h clean_kconfig drivers/net/wireless/ti/wlcore/Kconfig 'WLCORE' clean_mk CONFIG_WLCORE drivers/net/wireless/ti/wlcore/Makefile @@ -1835,12 +1880,7 @@ clean_kconfig drivers/staging/gdm72xx/Kconfig 'WIMAX_GDM72XX_SDIO' clean_mk CONFIG_WIMAX_GDM72XX_SDIO drivers/staging/gdm72xx/Makefile announce WIMAX_GDM72XX_USB - "GCT GDM72xx WiMAX support: USB interface" -clean_sed ' -/^int usb_boot/,/^}/ { - /filp = filp_open/ s,filp = .*;,/*(DEBLOBBED)*/, - s,if (IS_ERR(filp)),if (1 /*(DEBLOBBED)*/), -}' drivers/staging/gdm72xx/usb_boot.c \ - 'disabled non-Free firmware loading machinery' +reject_firmware drivers/staging/gdm72xx/usb_boot.c clean_blob drivers/staging/gdm72xx/usb_boot.c clean_kconfig drivers/staging/gdm72xx/Kconfig 'WIMAX_GDM72XX_USB' clean_mk CONFIG_WIMAX_GDM72XX_USB drivers/staging/gdm72xx/Makefile @@ -1942,12 +1982,30 @@ clean_mk CONFIG_LIRC_ZILOG drivers/staging/media/lirc/Makefile # Data acquisition # #################### +announce COMEDI_DAQBOARD2000 - "IOtech DAQboard/2000 support" +reject_firmware drivers/staging/comedi/drivers/daqboard2000.c +clean_blob drivers/staging/comedi/drivers/daqboard2000.c +clean_kconfig drivers/staging/comedi/Kconfig 'COMEDI_DAQBOARD2000' +clean_mk CONFIG_COMEDI_DAQBOARD2000 drivers/staging/comedi/drivers/Makefile + announce COMEDI_JR3_PCI - "JR3/PCI force sensor board support" reject_firmware drivers/staging/comedi/drivers/jr3_pci.c clean_blob drivers/staging/comedi/drivers/jr3_pci.c clean_kconfig drivers/staging/comedi/Kconfig 'COMEDI_JR3_PCI' clean_mk CONFIG_COMEDI_JR3_PCI drivers/staging/comedi/drivers/Makefile +announce COMEDI_ME_DAQ - "Meilhaus ME-2000i, ME-2600i, ME-3000vm1 support" +reject_firmware drivers/staging/comedi/drivers/me_daq.c +clean_blob drivers/staging/comedi/drivers/me_daq.c +clean_kconfig drivers/staging/comedi/Kconfig 'COMEDI_ME_DAQ' +clean_mk CONFIG_COMEDI_ME_DAQ drivers/staging/comedi/drivers/Makefile + +announce COMEDI_NI_PCIDIO - "NI PCI-DIO32HS, PCI-6533, PCI-6534 support" +reject_firmware drivers/staging/comedi/drivers/ni_pcidio.c +clean_blob drivers/staging/comedi/drivers/ni_pcidio.c +clean_kconfig drivers/staging/comedi/Kconfig 'COMEDI_NI_PCIDIO' +clean_mk CONFIG_COMEDI_NI_PCIDIO drivers/staging/comedi/drivers/Makefile + announce COMEDI_USBDUX - "ITL USBDUX support" reject_firmware drivers/staging/comedi/drivers/usbdux.c clean_blob drivers/staging/comedi/drivers/usbdux.c @@ -2100,6 +2158,9 @@ clean_blob drivers/usb/misc/emi62.c clean_kconfig drivers/usb/misc/Kconfig 'USB_EMI62' clean_mk CONFIG_USB_EMI62 drivers/usb/misc/Makefile +announce USB_EZUSB_FX2 - "Functions for loading firmware on EZUSB chips" +maybe_reject_firmware drivers/usb/misc/ezusb.c + announce USB_ISIGHTFW - "iSight firmware loading support" reject_firmware drivers/usb/misc/isight_firmware.c clean_blob drivers/usb/misc/isight_firmware.c @@ -2152,16 +2213,10 @@ drop_fw_file firmware/keyspan/usa49w.HEX firmware/keyspan/usa49w.fw clean_kconfig drivers/usb/serial/Kconfig 'USB_SERIAL_KEYSPAN_USA49W' drop_fw_file firmware/keyspan/usa49wlc.HEX firmware/keyspan/usa49wlc.fw clean_kconfig drivers/usb/serial/Kconfig 'USB_SERIAL_KEYSPAN_USA49WLC' -reject_firmware drivers/usb/serial/keyspan.c clean_blob drivers/usb/serial/keyspan.c clean_kconfig drivers/usb/serial/Kconfig 'USB_SERIAL_KEYSPAN' clean_mk CONFIG_USB_SERIAL_KEYSPAN drivers/usb/serial/Makefile -announce USB_SERIAL_KEYSPAN_PDA - "USB Keyspan PDA Single Port Serial Driver" -clean_sed ' -s,request_ihex_firmware,/*KEYSPAN_PDA*/&, -' drivers/usb/serial/keyspan_pda.c 'accept Free firmware' - announce USB_SERIAL_EDGEPORT - "USB Inside Out Edgeport Serial Driver" clean_fw firmware/edgeport/boot.H16 firmware/edgeport/boot.fw clean_fw firmware/edgeport/boot2.H16 firmware/edgeport/boot2.fw @@ -2194,7 +2249,6 @@ announce USB_SERIAL_WHITEHEAT - "USB ConnectTech WhiteHEAT Serial Driver" clean_fw firmware/whiteheat.HEX firmware/whiteheat.fw clean_fw firmware/whiteheat_loader.HEX firmware/whiteheat_loader.fw clean_fw firmware/whiteheat_loader_debug.HEX firmware/whiteheat_loader_debug.fw -reject_firmware drivers/usb/serial/whiteheat.c clean_blob drivers/usb/serial/whiteheat.c clean_kconfig drivers/usb/serial/Kconfig 'USB_SERIAL_WHITEHEAT' clean_mk CONFIG_USB_SERIAL_WHITEHEAT drivers/usb/serial/Makefile @@ -2211,6 +2265,18 @@ clean_mk CONFIG_UWB_I1480U drivers/uwb/i1480/dfu/Makefile +############## +# RemoteProc # +############## + +announce STE_MODEM_RPROC - "STE-Modem remoteproc support" +maybe_reject_firmware drivers/remoteproc/remoteproc_core.c +undefine_macro SPROC_MODEM_FIRMWARE "\"/*(DEBLOBBED)*/\"" \ + "disabled non-Free firmware" drivers/remoteproc/ste_modem_rproc.c +clean_kconfig drivers/remoteproc/Kconfig 'STE_MODEM_RPROC' +clean_mk CONFIG_STE_MODEM_RPROC drivers/remoteproc/Makefile + + ######### # Sound # ######### @@ -2467,6 +2533,12 @@ clean_mk CONFIG_SND_SOC_ADAU1701 sound/soc/codecs/Makefile announce SND_SOC_SIGMADSP - "SigmaStudio firmware loader" maybe_reject_firmware sound/soc/codecs/sigmadsp.c +announce SND_SOC_WM0010 - "WM0010 DSP driver" +reject_firmware sound/soc/codecs/wm0010.c +clean_blob sound/soc/codecs/wm0010.c +clean_kconfig sound/soc/codecs/Kconfig 'SND_SOC_WM0010' +clean_mk CONFIG_SND_SOC_WM0010 sound/soc/codecs/Makefile + # It's not clear that wm2000_anc.bin is pure data. # Check with developer, clean up for now. announce SND_SOC_WM2000 - "WM2000 ALSA Soc Audio codecs" diff --git a/freed-ora/current/f18/deblob-check b/freed-ora/current/f18/deblob-check index ff1ba48aa..794eab404 100755 --- a/freed-ora/current/f18/deblob-check +++ b/freed-ora/current/f18/deblob-check @@ -1,6 +1,6 @@ #! /bin/sh -# deblob-check version 2012-10-31 +# deblob-check version 2012-11-27 # Inspired in gNewSense's find-firmware script. # Written by Alexandre Oliva <lxoliva@fsfla.org> @@ -1026,8 +1026,8 @@ set_except () { initnc '[ ]int[ ]bcomm_irq\[3[*]16\][ ]=' initnc '[ ]static[ ]const[ ]int8[ ]countLeadingZerosHigh\[\][ ]=' initnc 'static[ ]struct[ ]nic_qp_map[ ]nic_qp_mapping_[01]\[\][ ]=' - initnc 'static[ ]struct[ ]regval[ ]ov_initvals\[\][ ]=' - initnc 'static[ ]struct[ ]regval[ ]stk1125_initvals\[\][ ]=' + initnc 'static[ ]struct[ ]regval[ ]ov_initvals\[\][ ]=' drivers/media/usb/stkwebcam/stk-sensor.c + initnc 'static[ ]struct[ ]regval[ ]stk1125_initvals\[\][ ]=' drivers/media/usb/stkwebcam/stk-webcam.c initnc 'static[ ]u8[ ]bnx2x_stats_len_arr\[BNX2X_NUM_STATS\][ ]=' defsnc 'static[ ]const[ ]struct[ ]arb_line[ ]read_arb_data\[NUM_RD_Q\]\[MAX_RD_ORD[ ][+][ ]1\][ ]=' drivers/net/bnx2x/bnx2x_init_opts.h defsnc 'static[ ]const[ ]struct[ ]arb_line[ ]write_arb_data\[NUM_WR_Q\]\[MAX_WR_ORD[ ][+][ ]1\][ ]=' drivers/net/bnx2x/bnx2x_init_opts.h @@ -1061,7 +1061,7 @@ set_except () { accept ':03000000020200F9[\n]:040023000205\(9B0037\|5F0073\)[\n]\(:050030000000000000CB[\n]\|:0400430002010000B6[\n]\)*'"$sepx$blobpat*"'[\n]:\(0E06E0006400670065007400060334003700F4\|0606A000060334003700E0\)[\n]:00000001FF' 'firmware/keyspan_pda/\(keyspan_pda\|xircom_pgs\).HEX' accept ':100000000C004000000000000000000000000000A4[\n]'"$sepx$blobpat*"'[\n][/][*][ ]DSP56001[ ]bootstrap[ ]code[ ][*][/]' firmware/dsp56k/bootstrap.bin.ihex initnc 'static[ ]const[ ]u16[ ]uda1380_reg\[UDA1380_CACHEREGNUM\][ ]=' sound/soc/codecs/uda1380.c - initnc 'static[ ]const[ ]u16[ ]wm8510_reg\[WM8510_CACHEREGNUM\][ ]=' sound/soc/codecs/wm8510.c + defsnc 'static[ ]const[ ]u16[ ]wm8510_reg\[WM8510_CACHEREGNUM\][ ]=' sound/soc/codecs/wm8510.c initnc 'static[ ]const[ ]unsigned[ ]short[ ]atkbd_unxlate_table\[128\][ ]=' drivers/input/keyboard/atkbd.c initnc 'static[ ]const[ ]unsigned[ ]char[ ]usb_kbd_keycode\[256\][ ]=' drivers/hid/usbhid/usbkbd.c initnc '[ ][ ]u8[ ]buf,[ ]bufs\[\][ ]=' drivers/media/dvb/dvb-usb/cxusb.c @@ -1842,7 +1842,7 @@ set_except () { initc 'static[ ]uint32_t[ ]cuda_images\[\]\[PCXW_IMAGE_SIZE[/]sizeof[(]uint32_t[)]\][ ]__read_mostly[ ]=' # These are regarded as ok - initnc 'static[ ]const[ ]u8[ ]SN9C102_\(Y\|UV\)_QTABLE[01]\[64\][ ]=[ ][{]' + initnc 'static[ ]const[ ]u8[ ]SN9C102_\(Y\|UV\)_QTABLE[01]\[64\][ ]=[ ][{]' drivers/media/usb/sn9c102/sn9c102_config.h initnc '[ ]static[ ]\(const[ ]\)\?u8[ ]jpeg_header\[589\][ ]=[ ][{]' media/video/sn9c102/sn9c102_core.c accept '[ ][ ]\?err[ ]=[ ]sn9c102_write_const_regs[(]cam\(,[ \n]\+[{]0x[0-9a-fA-F][0-9a-fA-F],[ ]0x[0-9a-fA-F][0-9a-fA-F][}]\)*[)][;]' @@ -1897,24 +1897,24 @@ set_except () { initnc '[ ]static[ ]const[ ]unsigned[ ]int[ ]avg_pkts\[NCCTRL_WIN\][ ]=' initnc '[ ]static[ ]const[ ]unsigned[ ]short[ ]ac97_defaults\[\][ ]=' initnc '[ ]static[ ]int[ ]exp_lut\[256\][ ]=' - initnc '[ ]static[ ]u16[ ]jpeg_tables\[\]\[70\][ ]=' - initnc '[ ]static[ ]u16[ ]tables\[\][ ]=' + defsnc '[ ]static[ ]u16[ ]jpeg_tables\[\]\[70\][ ]=' drivers/media/pci/meye/meye.c + defsnc '[ ]static[ ]u16[ ]tables\[\][ ]=' drivers/media/pci/meye/meye.c initnc '[ ]static[ ]u32[ ]logMagTable\[128\][ ]=' - initnc '[ ]static[ ]u8[ ]init_bufs\[13\]\[5\][ ]=' + defsnc '[ ]static[ ]u8[ ]init_bufs\[13\]\[5\][ ]=' drivers/media/pci/cx88/cx88-cards.c initnc '[ ]static[ ]u_short[ ]geometry_table\[\]\[[45]\][ ]=' initnc '[ ]static[ ]unsigned[ ]char[ ]CRCTable1\[\][ ]=' initnc '[ ]static[ ]unsigned[ ]char[ ]CRCTable2\[\][ ]=' initnc '[ ]static[ ]unsigned[ ]char[ ]default_colors\[\][ ]=' - initnc '[ ]static[ ]unsigned[ ]char[ ]iso_regs\[8\]\[4\][ ]=' + defsnc '[ ]static[ ]unsigned[ ]char[ ]iso_regs\[8\]\[4\][ ]=' drivers/media/usb/cpia2/cpia2_usb.c initnc '[ ]static[ ]unsigned[ ]char[ ]log_scale\[101\][ ]=' sound/oss/pss.c initnc '[ ]static[ ]unsigned[ ]char[ ]msg\[\][ ]=' - initnc '[ ]static[ ]unsigned[ ]char[ ]static_pad\[\][ ]=' + defsnc '[ ]static[ ]unsigned[ ]char[ ]static_pad\[\][ ]=' drivers/s390/crypto/zcrypt_msgtype6.c defsnc '[ ]static[ ]unsigned[ ]char[ ]table_alaw2ulaw\[\][ ]=' drivers/staging/telephony/ixj.c defsnc '[ ]static[ ]unsigned[ ]char[ ]table_ulaw2alaw\[\][ ]=' drivers/staging/telephony/ixj.c defsnc '[ ]\(static[ ]const[ ]\)\?u32[ ]reg_boundaries\[\][ ]=' drivers/net/bnx2.c - initnc '[ ]u8[ ]b\[\][ ]=' + defsnc '[ ]u8[ ]b\[\][ ]=' drivers/media/usb/ttusb-dec/ttusbdecfe.c initnc '[ ]uint8_t[ ]tx\[\][ ]=' - initnc '[ ]unsigned[ ]char[ ]saa7111_regs\[\][ ]=' + defsnc '[ ]unsigned[ ]char[ ]saa7111_regs\[\][ ]=' drivers/media/parport/w9966.c initnc '[ ]unsigned[ ]char[ ]sas_pcd_m_pg\[\][ ]=' initnc '[ ][}][ ]modedb\[5\][ ]=' defsnc '[ ][}][ ]reg_tbl\[\][ ]=' drivers/net/bnx2.c @@ -1994,7 +1994,7 @@ set_except () { initnc 'static[ ]const[ ]u32[ ]SS[0-3]\[256\][ ]=' initnc 'static[ ]const[ ]u32[ ]S[1-8]\[64\][ ]=' initnc 'static[ ]const[ ]u32[ ]T[0-5]\[256\][ ]=' - initnc 'static[ ]const[ ]u32[ ]Tm\[24\]\[8\][ ]=' + defsnc 'static[ ]const[ ]u32[ ]Tm\[24\]\[8\][ ]=' crypto/cast6_generic.c initnc 'static[ ]const[ ]u32[ ]bass_table\[41\]\[5\][ ]=' initnc 'static[ ]const[ ]u32[ ]bf_sbox\[256[ ][*][ ]4\][ ]=' defsnc 'static[ ]const[ ]u32[ ]camellia_sp0222\[256\][ ]=' crypto/camellia.c @@ -2006,14 +2006,14 @@ set_except () { initnc 'static[ ]const[ ]u32[ ]m8xx_size_to_gray\[M8XX_SIZES_NO\][ ]=' initnc 'static[ ]const[ ]u32[ ]mds\[4\]\[256\][ ]=' initnc 'static[ ]const[ ]u32[ ]pc2\[1024\][ ]=' - initnc 'static[ ]const[ ]u32[ ]s[1-7]\[256\][ ]=' - initnc 'static[ ]const[ ]u32[ ]sb8\[256\][ ]=' + defsnc 'static[ ]const[ ]u32[ ]s[1-7]\[256\][ ]=' crypto/cast5_generic.c + defsnc 'static[ ]const[ ]u32[ ]sb8\[256\][ ]=' crypto/cast5_generic.c initnc 'static[ ]const[ ]u32[ ]tfrc_calc_x_lookup\[TFRC_CALC_X_ARRSIZE\]\[2\][ ]=' initnc 'static[ ]const[ ]u32[ ]treble_table\[41\]\[5\][ ]=' initnc 'static[ ]const[ ]u64[ ][CT][0-7]\[256\][ ]=' initnc 'static[ ]const[ ]u64[ ]sbox[1-4]\[256\][ ]=' initnc 'static[ ]const[ ]u64[ ]sha512_K\[80\][ ]=' 'crypto/sha512\(_generic\)\?.c' - initnc 'static[ ]const[ ]u8[ ]Tr\[4\]\[8\][ ]=' + defsnc 'static[ ]const[ ]u8[ ]Tr\[4\]\[8\][ ]=' crpto/cast6_generic.c initnc 'static[ ]const[ ]u8[ ]aes_sbox\[256\][ ]=' initnc 'static[ ]const[ ]u8[ ]calc_sb_tbl\[512\][ ]=' initnc 'static[ ]const[ ]u8[ ]exp_to_poly\[492\][ ]=' @@ -2038,16 +2038,16 @@ set_except () { initnc 'static[ ]const[ ]unsigned[ ]char[ ]comet_miireg2offset\[32\][ ]=' initnc 'static[ ]\(const[ ]\)\?unsigned[ ]char[ ]euc2sjisibm_g3upper_map\[\]\[2\][ ]=' initnc 'static[ ]const[ ]unsigned[ ]char[ ]green\[256\][ ]=' - initnc 'static[ ]const[ ]unsigned[ ]char[ ]hash_table_ops\[64[*]4\][ ]=' + defsnc 'static[ ]const[ ]unsigned[ ]char[ ]hash_table_ops\[64[*]4\][ ]=' drivers/media/usb/pwc/pwc-dec23.c defsnc 'static[ ]const[ ]unsigned[ ]char[ ]hid_keyboard\[256\][ ]=' drivers/hid/hid-input.c initnc 'static[ ]const[ ]unsigned[ ]char[ ]mts_direction\[256[/]8\][ ]=' initnc 'static[ ]const[ ]unsigned[ ]char[ ]red\[256\][ ]=' initnc 'static[ ]\(const[ ]\)\?unsigned[ ]char[ ]sjisibm2euc_map\[\]\[2\][ ]=' initnc 'static[ ]const[ ]unsigned[ ]char[ ]vol_cvt_datt\[128\][ ]=' - initnc 'static[ ]const[ ]unsigned[ ]int[ ]MulIdx\[16\]\[16\][ ]=' + defsnc 'static[ ]const[ ]unsigned[ ]int[ ]MulIdx\[16\]\[16\][ ]=' drivers/media/usb/pwc/pwc-dec23.c initnc 'static[ ]const[ ]unsigned[ ]int[ ]crctab32\[\][ ]=' initnc 'static[ ]const[ ]unsigned[ ]short[ ]crc_flex_table\[\][ ]=' - initnc 'static[ ]const[ ]unsigned[ ]short[ ]logtable\[256\][ ]=' + defsnc 'static[ ]const[ ]unsigned[ ]short[ ]logtable\[256\][ ]=' drivers/media/dvb-core/dvb_math.c initnc 'static[ ]const[ ]unsigned[ ]short[ ]wd7000_iobase\[\][ ]=' defsnc 'static[ ]const[ ]unsigned[ ]short[ ]x86_keycodes\[256\][ ]=' drivers/tty/vt/keyboard.c initnc 'static[ ]const[ ]unsigned[ ]table\[\][ ]=' @@ -2066,7 +2066,7 @@ set_except () { initnc 'static[ ]short[ ]isdn_audio_[ua]law_to_s16\[\][ ]=' defsnc 'static[ ]struct[ ]iw\?l\(3945\)\?_tx_power[ ]power_gain_table\[2\]\[IW\?L_MAX_GAIN_ENTRIES\][ ]=' drivers/net/wireless/iwlegacy/iwl-3945.c initnc 'static[ ]struct[ ]ovcamchip_regvals[ ]regvals_init_\(76be\|7[16]20\|7x10\)\[\][ ]=' - initnc 'static[ ]struct[ ]regval_list[ ]ov7670_default_regs\[\][ ]=' + initnc 'static[ ]struct[ ]regval_list[ ]ov7670_default_regs\[\][ ]=' drivers/media/i2c/ov7670.c initnc 'static[ ]struct[ ]s_c2[ ]SetRate48000\[\][ ]=' initnc 'static[ ]struct[ ]tea6420_multiplex[ ]TEA6420_line\[MXB_AUDIOS[+]1\]\[2\][ ]=' initnc 'static[ ]struct[ ]wm_info[ ]i810_wm_16_100\[\][ ]=' @@ -2079,15 +2079,15 @@ set_except () { initnc 'static[ ]u16[ ]asEqCoefsPipes\[64\][ ]=' initnc 'static[ ]u16[ ]asEqCoefsZeros\[50\][ ]=' initnc 'static[ ]u16[ ]asEqOutStateZeros\[48\][ ]=' - initnc 'static[ ]u16[ ]default_key_map[ ]\[256\][ ]=' + defsnc 'static[ ]u16[ ]default_key_map[ ]\[256\][ ]=' drivers/media/pci/ttpci/av7110_ir.c initnc 'static[ ]u16[ ]eq_levels\[64\][ ]=' initnc 'static[ ]u32[ ][ ]crc32tab\[\][ ]__attribute__[ ][(][(]aligned[(]8[)][)][)][ ]=' - initnc 'static[ ]u32[ ]ac3_frames\[3\]\[32\][ ]=' + defsnc 'static[ ]u32[ ]ac3_frames\[3\]\[32\][ ]=' drivers/media/dvb-core/dvb_filter.c initnc 'static[ ]u32[ ]adwDecim8\[33\][ ]=' initnc 'static[ ]u32[ ]h_prescale\[64\][ ]=' initnc 'static[ ]u32[ ]v_gain\[64\][ ]=' - initnc 'static[ ]u8[ ]SRAM_Table\[\]\[60\][ ]=' - initnc 'static[ ]u8[ ]alps_tdee4_stv0297_inittab\[\][ ]=' + defsnc 'static[ ]u8[ ]SRAM_Table\[\]\[60\][ ]=' drivers/media/pci/bt8xx/bttv-driver.c + defsnc 'static[ ]u8[ ]alps_tdee4_stv0297_inittab\[\][ ]=' drivers/media/common/b2c2/flexcop-fe-tuner.c defsnc 'static[ ]u8[ ]bnx2_570[68]_stats_len_arr\[BNX2_NUM_STATS\][ ]=' drivers/net/bnx2.c initnc 'static[ ]u8[ ]flit_desc_map\[\][ ]=' defsnc 'static[ ]\(const[ ]\)\?u8[ ]init_tab[ ]\?\[\][ ]=' 'drivers/media/dvb/frontends/cx2270\(0\|2\)\.c' @@ -2096,9 +2096,9 @@ set_except () { initnc 'static[ ]u8[ ]mt2131_config1\[\][ ]=' drivers/media/common/tuners/mt2131.c # >= 2.6.26 initnc 'static[ ]u8[ ]mt2266_init2\[\][ ]=' drivers/media/dvb/frontends/mt2266.c # <= 2.6.25 initnc 'static[ ]u8[ ]mt2266_init2\[\][ ]=' drivers/media/common/tuners/mt2266.c # >= 2.6.26 - initnc 'static[ ]u8[ ]opera1_inittab\[\][ ]=' - initnc 'static[ ]u8[ ]saa7113_init_regs\[\][ ]=' - initnc 'static[ ]u8[ ]samsung_tbmu24112_inittab\[\][ ]=' + defsnc 'static[ ]u8[ ]opera1_inittab\[\][ ]=' drivers/media/usb/dvb-usb/opera1.c + defsnc 'static[ ]u8[ ]saa7113_init_regs\[\][ ]=' drivers/media/pci/ttpci/av7110_v4l.c + defsnc 'static[ ]u8[ ]samsung_tbmu24112_inittab\[\][ ]=' drivers/media/common/b2c2/flexcop-fe-tuner.c defsnc 'static[ ]u8[ ]w1_crc8_table\[\][ ]=' drivers/w1/w1_io.c initnc 'static[ ]u_char[ ]const[ ]data_sizes_32\[32\][ ]=' initnc 'static[ ]u_long[ ]ident_map\[32\][ ]=' @@ -2131,7 +2131,7 @@ set_except () { initnc 'static[ ]unsigned[ ]char[ ]crystal_key\[\][ ]=' initnc 'static[ ]unsigned[ ]char[ ]dsp_ulaw\[\][ ]=' initnc 'static[ ]unsigned[ ]char[ ]expressiontab\[128\][ ]=' - initnc 'static[ ]unsigned[ ]char[ ]header2\[\][ ]=' + defsnc 'static[ ]unsigned[ ]char[ ]header2\[\][ ]=' drivers/media/usb/zr364xx/zr364xx.c initnc 'static[ ]unsigned[ ]char[ ]hidp_keycode\[256\][ ]=' initnc 'static[ ]unsigned[ ]char[ ]nkbd_keycode\[128\][ ]=' initnc 'static[ ]unsigned[ ]char[ ]pan_volumes\[256\][ ]=' @@ -2151,9 +2151,9 @@ set_except () { initnc 'static[ ]unsigned[ ]char[ ]voltab[12]\[128\][ ]=' initnc 'static[ ]unsigned[ ]char[ ]vpd89_data\[\][ ]=' initnc 'static[ ]unsigned[ ]char[ ]xtkbd_keycode\[256\][ ]=' - initnc 'static[ ]unsigned[ ]int[ ]ac3_bitrates\[32\][ ]=' + defsnc 'static[ ]unsigned[ ]int[ ]ac3_bitrates\[32\][ ]=' drivers/media/dvb-core/dvb_filter.c initnc 'static[ ]unsigned[ ]int[ ]bass_volume_table\[\][ ]=' - initnc 'static[ ]unsigned[ ]int[ ]bitrates\[3\]\[16\][ ]=' + defsnc 'static[ ]unsigned[ ]int[ ]bitrates\[3\]\[16\][ ]=' drivers/media/dvb-core/dvb_filter.c initnc 'static[ ]unsigned[ ]int[ ]isa_dma_port\[8\]\[7\][ ]=' initnc 'static[ ]unsigned[ ]int[ ]master_volume_table\[\][ ]=' initnc 'static[ ]unsigned[ ]int[ ]mixer_volume_table\[\][ ]=' @@ -2187,17 +2187,17 @@ set_except () { initnc '\(uint16_t\|u16\)[ ]e1000_igp_2_cable_length_table\[IGP02E1000_AGC_LENGTH_TABLE_SIZE\][ ]=' drivers/net/e1000/e1000_hw.c # u16 on 2.6.26 initnc '[}][ ]euc2sjisibm_jisx0212_map\[\][ ]=' initnc '[}][ ]freq\[\][ ]=' - initnc '[}][ ]hps_h_coeff_tab[ ]\[\][ ]=' - initnc '[}][ ]hps_v_coeff_tab[ ]\[\][ ]=' - initnc '[}][ ]init_tab\[\][ ]=' + defsnc '[}][ ]hps_h_coeff_tab[ ]\[\][ ]=' drivers/media/common/saa7146/saa7146_hlp.c + defsnc '[}][ ]hps_v_coeff_tab[ ]\[\][ ]=' drivers/media/common/saa7146/saa7146_hlp.c + defsnc '[}][ ]init_tab\[\][ ]=' drivers/media/dvb-frontends/s5h1409.c initnc '[}][ ]maven_gamma\[\][ ]=' defsnc '[}][ ]mem_table\[\][ ]=' drivers/net/ethernet/8390/smc-mca.c - initnc '[}][ ]mxb_saa7740_init\[\][ ]=' + defsnc '[}][ ]mxb_saa7740_init\[\][ ]=' drivers/media/pci/saa7146/mxb.c initnc '[}][ ]pll_table\[\][ ]=' drivers/video/geode/lxfb_ops.c - initnc '[}][ ]qam256_snr_tab\[\][ ]=' - initnc '[}][ ]qam64_snr_tab\[\][ ]=' + defsnc '[}][ ]qam256_snr_tab\[\][ ]=' drivers/media/dvb-frontends/s5h1409.c + defsnc '[}][ ]qam64_snr_tab\[\][ ]=' drivers/media/dvb-frontends/s5h1409.c initnc '[}][ ]sil_port\[\][ ]=' - initnc '[}][ ]vsb_snr_tab\[\][ ]=' + defsnc '[}][ ]vsb_snr_tab\[\][ ]=' drivers/media/dvb-frontends/s5h1409.c # new in 2.6.30 defsnc 'static[ ]const[ ]unsigned[ ]char[ ]sync\[\][ ]=' Documentation/networking/timestamping/timestamping.c @@ -3147,6 +3147,89 @@ set_except () { blobname 'rtl_nic[/]rtl8168g-1\.fw' drivers/net/ethernet/realtek/r8169.c defsnc '[ ]static[ ]const[ ]u16[ ]mac_ocp_patch\[\][ ]=' in drivers/net/ethernet/realtek/r8169.c blobname 'rt3290\.bin\(\.[\n][ ][ ][*][/]\)\?' drivers/net/wireless/rt2x00/rt2800pci.h + + # New in 3.7: + blobname 'imx[/]sdma[/]sdma-imx6q-to1\.bin' arch/arm/boot/dts/imx6q.dtsi + accept 'AES_T[ed]:\([\n]\.word[ ]0x[0-9a-f]*\([,][ ]0x[0-9a-f]*\)*\)*[\n][@][ ]T[ed]4\[256\]\([\n]\.byte[ ]0x[0-9a-f]*\([,][ ]0x[0-9a-f]*\)*\)*\([\n][@][ ]rcon\[\]\([\n]\.word[ ]0x[0-9a-f]*\([,][ ]0x[0-9a-f]*\)*\)*\([,][ ]0\)*\)\?' arch/arm/crypto/aes-armv4.S + defsnc 'const[ ]u32[ ]cast5_s[1234]\[256\][ ]=' crypto/cast5_generic.c + defsnc 'const[ ]u32[ ]cast6_s[1234]\[256\][ ]=' crypto/cast6_generic.c + accept '[ ][*][ ]Once[ ]it[ ]returns[ ]successfully[,][ ]driver[ ]can[ ]use[ ]request_firmware' drivers/base/firmware_class.c + accept 'int[\n ]cache_firmware[(]const[ ]char[ ][*]fw_name[)][\n][{]\([\n]\+[^\n}][^\n]*\)*ret[ ]=[ ]request_firmware[(][^\n]*\([\n]\+[^\n}][^\n]*\)*[\n]\+[}][\n]' drivers/base/firmware_class.c + accept '[ ][*][ ]If[ ]one[ ]device[ ]called[ ]request_firmware' drivers/base/firmware_class.c + defsnc 'static[ ]const[ ]struct[ ]mV_pos[ ]__cpuinitconst[ ]\(vrm85\|mobilevrm\)_mV\[32\][ ]=' drivers/cpufreq/longhaul.h + defsnc 'static[ ]const[ ]unsigned[ ]char[ ]__cpuinitconst[ ]mV_\(vrm85\|mobilevrm\)\[32\][ ]=' drivers/cpufreq/longhaul.h + # Sources for these are in the corresponding .fuc files. + defsnc 'static[ ]u32[ ]nva3_pcopy_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h + defsnc 'static[ ]u32[ ]nvc0_pcopy_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h + defsnc 'static[ ]uint32_t[ ]nv98_pcrypt_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h + defsnc 'uint32_t[ ]nve0_grgpc_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h + defsnc 'uint32_t[ ]nve0_grhub_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h + defsnc 'nv04_graph_ctx_regs\[\][ ]=' drivers/gpu/drm/nouveau/core/engine/graph/nv04.c + accept '[ ]*ret[ ]=[ ]request_firmware[(]&fw[,][ ]source[,][ ]&nv_device[(]bios[)]->pdev->dev[)][;]' drivers/gpu/drm/nouveau/core/subdev/bios/base.c + defsnc 'static[ ]u8[ ][*]edid_load[(][^)]*[)][\n][{]\([\n]\+[^\n}][^\n]*\)*[^\n]*err[ ]=[ ]request_firmware[(][&]fw[,][ ]name[,][ ][&]pdev' drivers/gpu/drm/drm_edid_load.c + defsnc 'static[ ]const[ ]RegInitializer[ ]initData\[\][ ]__initconst[ ]=' drivers/ide/ali14xx.c + defsnc 'static[ ]const[ ]struct[ ]reg_val[ ]tuner_init_fc2580\[\][ ]=' drivers/media/dvb-frontends/af9033_priv.h + defsnc '[ ]static[ ]const[ ]u8[ ]bw_params1\[3\]\[34\][ ]=' drivers/media/dvb-frontends/rtl2830.c + blobname 's5k4ecgx\.bin' drivers/media/i2c/s5k4ecgx.c + blobname 'v4l-coda\(dx6-imx27\|7541-imx53\)\.bin' drivers/media/platform/coda.c + blobname 's5p-mfc\(-v6\)\?\.fw' drivers/media/platform/s5p-mfc/s5p_mfc.c + defsnc 'static[ ]const[ ]struct[ ]e4000_lna_filter[ ]e400_lna_filter_lut\[\][ ]=' drivers/media/tuners/e4000_priv.h + defsnc 'static[ ]const[ ]struct[ ]e4000_if_filter[ ]e4000_if_filter_lut\[\][ ]=' drivers/media/tuners/e4000_priv.h + defsnc 'static[ ]const[ ]struct[ ]fc2580_reg_val[ ]fc2580_init_reg_vals\[\][ ]=' drivers/media/tuners/fc2580_priv.h + defsnc 'static[ ]const[ ]struct[ ]fc2580_freq_regs[ ]fc2580_freq_regs_lut\[\][ ]=' drivers/media/tuners/fc2580_priv.h + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm5110_revb_patch\[\][ ]=' drivers/mfd/wm5110-tables.c + defsnc 'static[ ]struct[ ]nand_ecclayout[ ]lpc32xx_nand_oob[ ]=' drivers/mtd/nand/lpc32xx_mlc.c + defsnc 'static[ ]struct[ ]nand_ecclayout[ ]flctl_4secc_oob_64[ ]=' drivers/mtd/nand/sh_flctl.c + defsnc 'static[ ]const[ ]struct[ ]atl1c_platform_patch[ ]plats\[\][ ]__devinitconst[ ]=' drivers/net/ethernet/atheros/atl1c/atl1c_main.c + defsnc 'static[ ]const[ ]u32[ ]ar9565_1p0_\(\(mac\|baseband\|radio\)_core\|[Cc]ommon_\(wo_xlna_\)\?rx_gain_table\)\[\]\[2\][ ]=' drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h + defsnc 'static[ ]const[ ]u32[ ]ar9565_1p0_\(\(mac\|baseband\)_postamble\|[Mm]odes_\(low\(est\)\?\|high\)_\(ob_db\|power\)_tx_gain_table\)\[\]\[5\][ ]=' drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h + defsnc 'static[ ]u16[ ]r2057_rev[4578]a\?_init\[[45][245]\]\[2\][ ]=' drivers/net/wireless/b43/radio_2057.c + defsnc '[ ]*tbl_rf_control_override_rev7_over[01]\[\][ ]=' drivers/net/wireless/b43/tables_nphy.c + defsnc 'static[ ]const[ ]unsigned[ ]pci_pins\[\][ ]=' drivers/pinctrl/spear/pinctrl-spear1310.c + defsnc 'static[ ]int[ ]array_soc\[\]\[2\][ ]=' drivers/power/88pm860x_battery.c + defsnc 'static[ ]const[ ]int[ ]mc13783_sw[12]x_val\[\][ ]=' drivers/regulator/mc13783-regulator.c + # remoteproc uses request_firmware, but it is generic and names + # no blobs of its own, so we change it to maybe_request_firmware. + accept '[ ]ret[ ]=[ ]request_firmware_nowait[(]THIS_MODULE[,][ ]FW_ACTION_HOTPLUG[,][\n][ ]*rproc->firmware[,][ ][&]rproc->dev[,][ ]GFP_KERNEL[,][\n][ ]*rproc[,][ ]rproc_fw_config_virtio[)][;][\n][ ]if[ ][(]ret[ ]<[ ]0[)][ ][{][\n][ ][ ]dev_err[(][&]rproc->dev[,][ ]["]request_firmware_nowait[ ]err' drivers/remoteproc/remoteproc_core.c + # This remoteproc client does name blobs, but we discard it + # with undefine_macro. + blob 'SPROC_MODEM_NAME[ ]["]-fw\.bin["]' drivers/remoteproc/ste_modem_rproc.c + accept '[ ]if[ ][(]request_firmware[(]&fw_entry,[ ]fname,[ ]&ioa_cfg->pdev->dev[)][)]' drivers/scsi/ipr.c + blobname 'daqboard2000_firmware\.bin' drivers/staging/comedi/drivers/daqboard2000.c + blobname 'me2600_firmware\.bin' drivers/staging/comedi/drivers/me_daq.c + blobname 'ni6534a\.bin' drivers/staging/comedi/drivers/ni_pcidio.c + blobname 'niscrb0[12]\.bin' drivers/staging/comedi/drivers/ni_pcidio.c + defsnc 'static[ ]const[ ]struct[ ]SiS_TVData[ ]XGI_\(St\|Ext\)\(PAL\|NTSC\|YPbPr\(525\|750\)[ip]\)Data\[\][ ]=' drivers/staging/xgifb/vb_table.h + defsnc 'static[ ]const[ ]unsigned[ ]char[ ]XGI330_\(NTSC\|PAL\|HiTV\(Ext\|St[12]\|Text\)\|YPbPr\(525\|750\)[ip]\)Timing\[\][ ]=' drivers/staging/xgifb/vb_table.h + defsnc 'static[ ]const[ ]unsigned[ ]char[ ]XGI330_\(HiTV\|Ren\(525\|750\)p\)Group3\(Data\|Simu\|Text\)\?\[\][ ]=' drivers/staging/xgifb/vb_table.h + accept 'static[ ]inline[ ]int[\n]\(maybe_\)\?reject_ihex_firmware\(_nowait\)\?[(][^{;]*[)][\n][{]\([\n]\+[^\n}][^\n]*\)*[^\n]*[\n]\+[}]' include/linux/firmware.h + defsnc '[/][*][ ]callback[ ]from[ ]request_firmware_nowait' sound/pci/hda/hda_intel.c + defsnc 'static[ ]int[ ]__devinit[ ]azx_probe[(][^)]*[)][\n][{]\([\n]\+[^\n}][^\n]*\)*[^\n]*request_firmware[^\n]*' sound/pci/hda/hda_intel.c + defsnc 'static[ ]struct[ ]reg_default[ ]da9055_reg_defaults\[\][ ]=' sound/soc/codecs/da9055.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]sta32x_regs\[\][ ]=' sound/soc/codecs/sta32x.c + blobname 'wm0010\(_stage2\.bin\|\.dfw\)' sound/soc/codecs/wm0010.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm5102_sysclk_reva_patch\[\][ ]=' sound/soc/codecs/wm5102.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm8510_reg_defaults\[\][ ]=' sound/soc/codecs/wm8510.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm8580_reg_defaults\[\][ ]=' sound/soc/codecs/wm8580.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm8776_reg_defaults\[\][ ]=' sound/soc/codecs/wm8776.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm8900_reg_defaults\[\][ ]=' sound/soc/codecs/wm8900.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm8960_reg_defaults\[\][ ]=' sound/soc/codecs/wm8960.c + accept '[ ][ ]priv->firmware[ ]=[ ]true[;]' drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c + accept '[ ][ ]*\(if[ ][(]\|[ ][ ][ ][ ]\)nvc0_graph_ctor_fw[(]priv[,][ ]["]fuc4\(09\|1a\)[cd]["][,][ ][&]priv->fuc4\(09\|1a\)[cd][)]' 'drivers/gpu/drm/nouveau/core/engine/graph/nv[ce]0\.c' + accept '[ ][ ]*nvc0_graph_dtor_fw[(]&priv->fuc4\(09\|1a\)[cd][)][;]' 'drivers/gpu/drm/nouveau/nv[ce]0\.c' + accept '[ ][ ]*nvc0_graph_init_fw[(]priv[,][ ]0x4\(09\|1a\)000[,][ ][&]priv->fuc4\(09\|1a\)c[,][ \n ]*[&]priv->fuc4\(09\|1a\)d[)][;]' 'drivers/gpu/drm/nouveau/core/engine/graph/nv[ce]0\.c' + blobname 'dvb-fe-xc5000c-4\.1\.30\.7\.fw' drivers/media/tuners/xc5000.c + accept '[ ]\.firmware[ ]=[ ]AF9015_FIRMWARE' drivers/media/usb/dvb-usb-v2/af9015.c + accept '[ ]\.firmware[ ]=[ ]AF9035_FIRMWARE' drivers/media/usb/dvb-usb-v2/af9035.c + accept '[ ]\.firmware[ ]*=[ ]AZ6007_FIRMWARE' drivers/media/usb/dvb-usb-v2/az6007.c + accept '[ ]\.firmware[ ]=[ ]EC168_FIRMWARE' drivers/media/usb/dvb-usb-v2/ec168.c + blobname 'brcm[/]brcmfmac43\(143\|242a\)\.bin' drivers/net/wireless/brcm80211/brcmfmac/usb.c + accept '[ ]priv->firmware[ ]=[ ]fw[;]' drivers/net/wireless/p54/p54pci.c + blobname 'c[bt]2\?fw-3\.1\.0\.0\.bin' drivers/scsi/bfa/bfad.c + blobname 'gdmuimg\.bin' drivers/staging/gdm72xx/usb_boot.c + blobname 'CMV4[pi]\.bin\(\.v2\)\?' drivers/usb/atm/ueagle-atm.c + blobname 'dvb-fe-tda10071\.fw' drivers/media/dvb/frontends/tda10071_priv.h + accept '[ ]st->it913x_config\.firmware[ ]=' drivers/media/usb/dvb-usb-v2/it913x.c ;; */*freedo*.patch | */*logo*.patch) @@ -3158,6 +3241,350 @@ set_except () { accept 'MODULE_FIRMWARE[(]["]keyspan_pda[/]\(keyspan_pda\|xircom_pgs\)\.fw["][)][;]' drivers/usb/serial/keyspan_pda.c # Present in patch for 3.6.5. defsnc 'static[ ]const[ ]u32[ ]ar9300Modes_high_power_tx_gain_table_2p2\[\]\[5\][ ]=' drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h + # Specific to the 3.7 patch + accept '[ ]\.firmware[ ]*=[ ]["][/][*][(]DEBLOBBED[)][*][/]["]' + accept '[ ]\(p1100\|s660\|p7500\)->firmware[ ]=[ ]["][/][*][(]DEBLOBBED[)][*][/]["]' + accept '[ ]-[ ]calls[ ]request_firmware[(]' Documentation/firmware_class/README + accept '[ ]7[)],[ ]kernel:[ ]request_firmware[(]' Documentation/firmware_class/README + accept '[ ][ ]request_firmware[(][)][ ]returns[ ]non-zero' Documentation/firmware_class/README + accept '\(static[ ]\(int\|void\)[\n ]\)\?_request_firmware\(_prepare\|_cleanup\)\?[(]const[ ]struct[ ]firmware[ ][*][*]\?' drivers/base/firmware_class.c + accept '[ ][ ]_request_firmware_cleanup[(]firmware_p[)][;]' drivers/base/firmware_class.c + accept '[ ][*][ ]Asynchronous[ ]variant[ ]of[ ]request_firmware[(][)]' drivers/base/firmware_class.c + accept 'request_firmware\(_nowait\)\?[(]' drivers/base/firmware_class.c + accept 'static[ ]inline[ ]int[ ]request_firmware\(_nowait\)\?[(]' include/linux/firmware.h + accept '[ ][ ]err[ ]=[ ]request_firmware_nowait[(]THIS_MODULE,[ ]true,[ ]patch\[dev\],' sound/pci/hda/hda_intel.c + accept '[ ][{]0x00009e1c,[ ]0x0001cf9c,[ ]0x[0-9a-fx{},\n ]*' drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h + accept '[;][/][*]@@[ ]-391,17[ ][+]407,17[ ]@@[*][/][;][\n]\([ ]*[123],\)*[\n]\(\([ ]*[ 1234][0-9],\)*[\n]\)*[\n]\(\([ ]*[ 1234][0-9],\)*[\n]\)*\([ ]*1,\)*' scripts/dtc/dtc-lexer.lex.c_shipped + accept '[;][/][*]@@[ ]-395,16[ ][+]423,16[ ]@@[*][/][;][\n][ ]*0,\([ ]*2,\)*[\n]\(\([ ]*[ 1234][0-9],\)*[\n]\)*\([ ]*2,\)*' scripts/dtc/dtc-parser.tab.c_shipped + accept '[;][/][*]@@[ ]-418,45[ ][+]446,68[ ]@@[*][/][;][\n]\([ ]*[2],\)*[\n]\(\([ ]*[ 12][0-9],\)*[\n]\)*\([ ]*[12][0-9],\)*[ ]*24' scripts/dtc/dtc-parser.tab.c_shipped + + # Already in 3.6, but changed or moved thus present in patch to 3.7: + initnc '[/][*][\n][ ][*][ ]\(cfa_coef\|gamma\|luma_enhance\|noise_filter\)_table\.h[\n][ ][*]\([^\n]*[\n][ ][*]\)*[/]' 'drivers/media/video/omap3isp/\(cfa_coef\|gamma\|luma_enhance\|noise_filter\)_table\.h' + accept '[ ][ ][ ][/][*][ ]\(SQCIF\|QSIF\|QCIF\|SIF\|CIF\|VGA\)[ ][*][/][\n][ ][ ][ ][{][\n][ ][ ][ ][ ][ ][ ][{]'"$blobpat*" drivers/media/video/pwc/pwc-nala.h + accept 'FIRMWARE[ ]LOADER[ ][(]request_firmware[)]' MAINTAINERS + accept '[ ]INIT_WORK[(][&]fw_work->work[,][ ]request_firmware_work_func[)][;]' drivers/base/firmware_class.c + accept '[ ]\+request_firmware[(][)][ ]will[ ]hit[ ]an[ ]OOPS' drivers/media/dvb/frontends/dib7000p.c + defsnc 'static[ ]struct[ ]clk_pll_\(freq_\)\?table[ ]tegra_pll_[adpxm]_\(freq_\)\?table\[\][ ]=' arch/arm/mach-tegra/tegra2_clocks.c + defsnc 'static[ ]struct[ ]clk_pll_freq_table[ ]tegra_pll_[cu]_freq_table\[\][ ]=' arch/arm/mach-tegra/tegra30_clocks.c + defsnc 'const[ ]u64[ ]camellia_sp\(10011110\|22000222\|03303033\|00444404\|02220222\|30333033\|44044404\|11101110\)\[256\][ ]=' arch/x86/crypto/camellia_glue.c + defsnc 'static[ ]const[ ]u32[ ]s[1-7]\[256\][ ]=' crypto/cast5_generic.c + defsnc 'static[ ]const[ ]u32[ ]sb8\[256\][ ]=' crypto/cast5_generic.c + defsnc 'static[ ]const[ ]u32[ ]Tm\[24\]\[8\][ ]=' crypto/cast6_generic.c + defsnc 'static[ ]const[ ]u8[ ]Tr\[4\]\[8\][ ]=' crpto/cast6_generic.c + defsnc 'static[ ]struct[ ]cipher_testvec[ ]\(aes\|anubis\|bf\|camellia\|cts_mode\|des3_ede\|cast6\|salsa20_stream\|serpent\|tf\|tnepres\|xeta\|x\?tea\)\(_\(cbc\|ctr\(_rfc3686\)\?\|xts\)\)\?_\(enc\|dec\)_tv_template\[\][ ]=' 'crypto/\(tcrypt\|testmgr\).h' + accept '\([ ]request_firmware[(][)][ ]hotplug[ ]interface:[\n][ ]--*[\n].*[ ]\)\?-[ ]request_firmware_nowait[(][)][ ]is[ ]also[ ]provided[ ]for[ ]convenience' Documentation/firmware_class/README + accept '\(static[ ]\(int\|void\)[\n ]\)\?_request_firmware\(_prepare\|_cleanup\)\?[(]const[ ]struct[ ]firmware[ ][*][*]\?firmware\(_p\)\?[,)][^{]*[\n][{]\([\n]\+[^\n}][^\n]*\)*[^\n]*[\n]\+[}][\n]' drivers/base/firmware_class.c + accept 'static[ ]int[ ]_request_firmware_load[(]struct[ ]firmware_priv[ ][*]fw_priv[,]' drivers/base/firmware_class.c + accept 'static[ ]void[ ]request_firmware_work_func[(]struct[ ]work_struct[ ][*]work[)]' drivers/base/firmware_class.c + accept 'EXPORT_SYMBOL[(]request_firmware\(_nowait\)\?[)][;]' drivers/base/firmware_class.c + accept '[ ]fw_priv[ ]=[ ]_request_firmware_prepare[(][&]fw[,]' drivers/base/firmware_class.c + accept '[ ][ ]ret[ ]=[ ]_request_firmware_load[(]fw_priv[,]' drivers/base/firmware_class.c + accept '[ ][ ]_request_firmware_cleanup[(][&]fw[)][;]' drivers/base/firmware_class.c + defsnc 'uint32_t[ ]nvc0_grgpc_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h + defsnc 'uint32_t[ ]nvc0_grhub_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h + defsnc 'static[ ]int[ ]nv10_graph_ctx_regs[ ]\?\[\][ ]=' drivers/char/drm/nv10_graph.c + defsnc 'static[ ]int[ ]types\[0x80\][ ]=' drivers/gpu/drm/nouveau/nv50_vram.c + defsnc 'static[ ]const[ ]u8[ ]types\[256\][ ]=' drivers/gpu/drm/nouveau/nvc0_vram.c + defsnc 'static[ ]u8[ ]samsung_tbmu24112_inittab\[\][ ]=' drivers/media/common/b2c2/flexcop-fe-tuner.c + defsnc 'static[ ]u8[ ]alps_tdee4_stv0297_inittab\[\][ ]=' drivers/media/common/b2c2/flexcop-fe-tuner.c + defsnc '[}][ ]hps_h_coeff_tab[ ]\[\][ ]=' drivers/media/common/saa7146/saa7146_hlp.c + defsnc '[}][ ]hps_v_coeff_tab[ ]\[\][ ]=' drivers/media/common/saa7146/saa7146_hlp.c + defsnc 'static[ ]unsigned[ ]int[ ]bitrates\[3\]\[16\][ ]=' drivers/media/dvb-core/dvb_filter.c + defsnc 'static[ ]unsigned[ ]int[ ]ac3_bitrates\[32\][ ]=' drivers/media/dvb-core/dvb_filter.c + defsnc 'static[ ]u32[ ]ac3_frames\[3\]\[32\][ ]=' drivers/media/dvb-core/dvb_filter.c + defsnc 'static[ ]const[ ]unsigned[ ]short[ ]logtable\[256\][ ]=' drivers/media/dvb-core/dvb_math.c + defsnc 'static[ ]const[ ]struct[ ]af9013_coeff[ ]coeff_lut\[\][ ]=' drivers/media/dvb/frontends/af9013_priv.h + defsnc 'static[ ]\(const[ ]\)\?struct[ ]\(snr_table\|af9013_snr\)[ ]\(qpsk\|qam\(16\|64\)\)_snr_\(table\|lut\)\[\][ ]=' drivers/media/dvb/frontends/af9013_priv.h + defsnc 'static[ ]\(const[ ]\)\?struct[ ]\(regdesc\|af9013_reg_bit\)[ ]\(ofsm_init\|tuner_init_\(env77h11d5\|mt2060\(_2\)\?\|mxl500\(3d\|5\)\|qt1010\|mc44s803\|unknown\|tda18271\)\)\[\][ ]=' drivers/media/dvb/frontends/af9013_priv.h + defsnc '[ ]struct[ ]reg_val_mask[ ]tab\[\][ ]=' 'drivers/media/dvb/frontends/\(cxd2820r_\(c\|t2\)\|af9033\)\.c' + defsnc 'static[ ]const[ ]struct[ ]coeff[ ]coeff_lut\[\][ ]=' drivers/media/dvb/frontends/af9033_priv.h + defsnc 'static[ ]const[ ]struct[ ]val_snr[ ]\(qpsk\|qam\(16\|64\)\)_snr_lut\[\][ ]=' drivers/media/dvb/frontends/af9033_priv.h + defsnc 'static[ ]const[ ]struct[ ]reg_val[ ]\(ofsm_init\|tuner_init_\(tua9001\|fc0011\|mxl5007t\|tda18218\)\)\[\][ ]=' drivers/media/dvb/frontends/af9033_priv.h + defsnc '\(static[ ]\)\?\(const[ ]\)\?struct[ ]au8522_register_config[ ]lpfilter_coef\[\][ ]=' drivers/media/dvb/frontends/au8522_decoder.c + defsnc 'static[ ]struct[ ]mse2snr_tab[ ]\(vsb\|qam\(64\|256\)\)_mse2snr_tab\[\][ ]=' drivers/media/dvb/frontends/au8522.c + defsnc '[}][ ]\(VSB\|QAM\(64\|256\)\?\)_mod_tab\[\][ ]=' 'drivers/media/dvb/frontends/au8522\(_dig\)\?\.c' + defsnc 'static[ ]u8[ ]stv0288_bsbe1_d01a_inittab\[\][ ]=' drivers/media/dvb/frontends/bsbe1-d01a.h + defsnc 'static[ ]\(const[ ]\)\?u8[ ]init_tab[ ]\?\[\][ ]=' 'drivers/media/dvb/frontends/cx2270\(0\|2\)\.c' + defsnc 'static[ ]const[ ]u16[ ]dib0090_defaults\[\][ ]=' drivers/media/dvb/frontends/dib0090.c + defsnc 'static[ ]const[ ]struct[ ]dib0090_pll[ ]dib0090_\(p1g_\)\?pll_table\[\][ ]=' drivers/media/dvb/frontends/dib0090.c + defsnc '[ ]static[ ]u8[ ]sine\[\][ ]=' drivers/media/dvb/frontends/dib7000p.c + accept '[ ]\+request_firmware[(][)][ ]will[ ]hit[ ]an[ ]OOPS' drivers/media/dvb/frontends/dib7000p.c + defsnc '\(static[ ]const[ ]\)\?u32[ ]fe_info\[44\][ ]=' drivers/media/dvb/frontends/dib9000.c + defsnc 'static[ ]u8[ ]ds3000_dvbs2\?_init_tab\[\][ ]=' drivers/media/dvb/frontends/ds3000.c + defsnc '[ ]static[ ]const[ ]u16[ ]dvbs2_snr_tab\[\][ ]=' drivers/media/dvb/frontends/ds3000.c + defsnc 'static[ ]struct[ ]dvb_pll_desc[ ][^\n]*[ ]=[ ][{]' drivers/media/dvb/frontends/dvb-pll.c + defsnc 'static[ ]u8[ ]stv0288_earda_inittab\[\][ ]=' drivers/media/dvb/frontends/eds1547.h + defsnc 'static[ ]const[ ]struct[ ]reg_mod_vals[ ]reg_mod_vals_tab\[\][ ]=' drivers/media/dvb/frontends/hd29l2_priv.h + defsnc 'static[ ]struct[ ]adctable[ ]tab[1-8]\[\][ ]=' drivers/media/dvb/frontends/it913x-fe-priv.h + initnc '[}][ ]itd1000_\(lpf_pga\|fre_values\)\[\][ ]=' drivers/media/dvb/frontends/itd1000.c + defsnc 'static[ ]const[ ]struct[ ]cnr[ ]cnr_tab\[\][ ]=' drivers/media/dvb/frontends/mb86a16.c + defsnc 'static[ ]struct[ ]regdata[ ]mb86a20s_init\[\][ ]=' drivers/media/dvb/frontends/mb86a20s.c + defsnc '[ ]struct[ ]rtl2830_reg_val_mask[ ]tab\[\][ ]=' drivers/media/dvb/frontends/rtl2830.c + defsnc '[ ]static[ ]u8[ ]bw_params1\[3\]\[34\][ ]=' drivers/media/dvb/frontends/rtl2830.c + defsnc '[ ]static[ ]u8[ ]bw_params\[3\]\[32\][ ]=' drivers/media/dvb/frontends/rtl2832.c + defsnc '[}][ ]init_tab\[\][ ]=' drivers/media/dvb-frontends/s5h1409.c + defsnc '[}][ ]vsb_snr_tab\[\][ ]=' drivers/media/dvb-frontends/s5h1409.c + defsnc '[}][ ]qam256_snr_tab\[\][ ]=' drivers/media/dvb-frontends/s5h1409.c + defsnc '[}][ ]qam64_snr_tab\[\][ ]=' drivers/media/dvb-frontends/s5h1409.c + defsnc 'static[ ]struct[ ]regdata[ ]s921_init\[\][ ]=' drivers/media/dvb/frontends/s921.c + defsnc 'static[ ]u8[ ]serit_sp1511lhb_inittab\[\][ ]=' drivers/media/dvb/frontends/si21xx.c + defsnc 'static[ ]\(const[ ]\)\?struct[ ]stb0899_tab[ ]stb0899_\(cn\|dvbs2\?rf\|quant\|est\)_tab\[\][ ]=' drivers/media/dvb/frontends/stb0899_drv.c + defsnc 'static[ ]const[ ]struct[ ]stb6100_lkup[ ]lkup\[\][ ]=' drivers/media/dvb/frontends/stb6100.c + defsnc 'static[ ]u8[ ]stv0288_inittab\[\][ ]=' drivers/media/dvb/frontends/stv0288.c + defsnc 'static[ ]u8[ ]tda10021_inittab\[0x40\]=' drivers/media/dvb/frontends/tda10021.c + initnc '[}][ ]snr_tab\[\][ ]=' drivers/media/dvb/frontends/tda10048.c + defsnc '[ ]struct[ ]tda10071_reg_val_mask[ ]tab2\[\][ ]=' drivers/media/dvb/frontends/tda10071.c + defsnc '[ ]static[ ]u8[ ]InitRegs\[\][ ]=' drivers/media/dvb/frontends/tda18271c2dd.c + defsnc 'static[ ]struct[ ]SMapI[ ]m_RF_Cal_Map\[\][ ]=' drivers/media/dvb/frontends/tda18271c2dd_maps.h + defsnc 'static[ ]struct[ ]SMap2[ ]m_\(Main\|Cal\)_PLL_Map\[\][ ]=' drivers/media/dvb/frontends/tda18271c2dd_maps.h + defsnc 'static[ ]struct[ ]SMap2\?[ ]*m_\(GainTaper\|RF_Cal_DC_Over_DT\|CID_Target\)_Map\[\][ ]=' drivers/media/dvb/frontends/tda18271c2dd_maps.h + defsnc 'static[ ]u8[ ]tda8083_init_tab[ ]\[\][ ]=' drivers/media/dvb/frontends/tda8083.c + defsnc 'static[ ]u8[ ]ves1820_inittab\[\][ ]=' drivers/media/dvb/frontends/ves1820.c + defsnc 'static[ ]u8[ ]init_1[89]93_w\?tab[ ]\?\[\][ ]=' drivers/media/dvb/frontends/ves1x93.c + defsnc '[ ]static[ ]const[ ]u8[ ]biphase_tbl\[\][ ]=' + initnc 'static[ ]struct[ ]regval_list[ ]ov7670_default_regs\[\][ ]=' drivers/media/i2c/ov7670.c + defsnc 'static[ ]struct[ ]s5k6aa_regval[ ]s5k6aa_analog_config\[\][ ]=' drivers/media/video/s5k6aa.c + initnc 'static[ ]u32[ ]reg_init_initialize\[\][ ]=' drivers/media/video/saa717x.c + initnc '[ ][}][ ]vals\[\][ ]=' drivers/media/video/saa717x.c + defsnc 'static[ ]const[ ]struct[ ]regval_list[ ]ov2640_init_regs\[\][ ]=' drivers/media/video/ov2640.c + defsnc 'static[ ]struct[ ]regval_list[ ]ov5642_default_regs_\(init\|finalise\)\[\][ ]=' drivers/media/video/ov5642.c + defsnc 'static[ ]const[ ]struct[ ]ov9640_reg[ ]ov9640_regs_dflt\[\][ ]=' drivers/media/video/ov9640.c + defsnc 'static[ ]const[ ]struct[ ]ov9740_reg[ ]ov9740_defaults\[\][ ]=' drivers/media/video/ov9740.c + defsnc '\(const[ ]static\|static[ ]const\)[ ]struct[ ]rj54n1_reg_val[ ]bank_[4578]\[\][ ]=' drivers/media/video/rj54n1cb0c.c + defsnc 'static[ ]const[ ]u16[ ]vs6624_p1\[\][ ]=' drivers/media/video/vs6624.c + defsnc '[ ]unsigned[ ]char[ ]saa7111_regs\[\][ ]=' drivers/media/parport/w9966.c + initnc 'static[ ]int[ ]miro_fmtuner\[\][ ][ ]=' drivers/media/video/bt8xx/bt-cards.c + initnc 'static[ ]int[ ]miro_tunermap\[\][ ]=' drivers/media/video/bt8xx/bt-cards.c + defsnc 'static[ ]u8[ ]SRAM_Table\[\]\[60\][ ]=' drivers/media/pci/bt8xx/bttv-driver.c + defsnc '[ ]static[ ]u8[ ]init_bufs\[13\]\[5\][ ]=' drivers/media/pci/cx88/cx88-cards.c + defsnc 'static[ ]\(const[ ]\)\?u8[ ]samsung_smt_7020_inittab\[\][ ]=' drivers/media/video/cx88/cx88-dvb.c + initnc '[ ]static[ ]const[ ]u8[ ]mpeg_hdr_data\[\][ ]=' drivers/media/video/cx18/cx18-vbi.c + defsnc 'u8[ ]lgtdqcs001f_inittab\[\][ ]=' drivers/media/dvb/mantis/mantis_vp1033.c + defsnc '[ ]static[ ]u16[ ]jpeg_tables\[\]\[70\][ ]=' drivers/media/pci/meye/meye.c + defsnc '[ ]static[ ]u16[ ]tables\[\][ ]=' drivers/media/pci/meye/meye.c + defsnc 'static[ ]u8[ ]ITUDecoderSetup\[4\]\[16\][ ]=' drivers/media/dvb/ngene/ngene-core.c + defsnc 'static[ ]const[ ]u8[ ]va1j5jf8007[ts]_\(2[05]mhz_\)\?prepare_bufs\[\]\[2\][ ]=' 'drivers/media/dvb/pt1/va1j5jf8007[st]\.c' + defsnc '[}][ ]mxb_saa7740_init\[\][ ]=' drivers/media/pci/saa7146/mxb.c + defsnc 'static[ ]u8[ ]nexusca_stv0297_inittab\[\][ ]=' drivers/media/dvb/ttpci/av7110.c + accept '[ ]const[ ]char[ ]\*fw_name[ ]=[ ]["]av7110[/]bootcode\.bin["][;]' drivers/media/dvb/ttpci/av7110_hw.c + accept '[ ]ret[ ]=[ ]request_firmware[(][^;]*[)][;][\n][ ]if[ ][(]ret[)][ ][{][^}]*[}][\n][\n][ ]mwdebi[(]av7110,[ ]DEBISWAB,[ ]DPRAM_BASE' drivers/media/dvb/ttpci/av7110_fw.c + accept 'MODULE_FIRMWARE[(]["]av7110[/]bootcode\.bin["][)][;]' drivers/media/dvb/ttpci/av7110_fw.c + defsnc 'static[ ]u16[ ]default_key_map[ ]\[256\][ ]=' drivers/media/pci/ttpci/av7110_ir.c + defsnc 'static[ ]u8[ ]saa7113_init_regs\[\][ ]=' drivers/media/pci/ttpci/av7110_v4l.c + defsnc 'static[ ]const[ ]u8[ ]saa7113_tab\[\][ ]=' drivers/media/dvb/ttpci/budget-av.c + defsnc 'static[ ]u8[ ]philips_sd1878_inittab\[\][ ]=' drivers/media/dvb/ttpci/budget-av.c + defsnc 'static[ ]u8[ ]philips_su1278_tt_inittab\[\][ ]=' drivers/media/dvb/ttpci/budget-ci.c + defsnc 'static[ ]u8[ ]dvbc_philips_tdm1316l_inittab\[\][ ]=' drivers/media/dvb/ttpci/budget-ci.c + defsnc 'static[ ]const[ ]char[ ]zr360[56]0_dqt\[0x86\][ ]=' 'drivers/media/video/zr36060\.c\|drivers/media/video/zoran/zr36060\.c' + defsnc 'static[ ]const[ ]char[ ]zr360[56]0_dht\[0x1a4\][ ]=' 'drivers/media/video/zr36060\.c\|drivers/media/video/zoran/zr36060\.c' + defsnc 'static[ ]const[ ]char[ ]zr360[56]0_dqt\[0x86\][ ]=' 'drivers/media/video/zr36060\.c\|drivers/media/video/zoran/zr36060\.c' + defsnc 'static[ ]const[ ]struct[ ]isprsz_coef[ ]filter_coefs[ ]=' drivers/media/video/omap3isp/ispresizer.c + defsnc 'static[ ]const[ ]unsigned[ ]char[ ]qtbl_\(lu\|chro\)minance\[4\]\[64\][ ]=' drivers/media/video/s5p-jpeg/jpeg-core.c + defsnc 'static[ ]const[ ]unsigned[ ]char[ ]hactblg0\[162\][ ]=' drivers/media/video/s5p-jpeg/jpeg-core.c + defsnc 'static[ ]const[ ]struct[ ]hdmiphy_conf[ ]hdmiphy_conf_\(s5pv210\|exynos4[24]1[02]\)\[\][ ]=' drivers/media/video/s5p-tv/hdmiphy_drv.c + defsnc 'static[ ]const[ ]u8[ ]filter_y_vert_tap4\[\][ ]=' drivers/media/video/s5p-tv/mixer_reg.c + initnc 'static[ ]u8[ ]mt2131_config1\[\][ ]=' drivers/media/common/tuners/mt2131.c # >= 2.6.26 + initnc 'static[ ]u8[ ]mt2266_init2\[\][ ]=' drivers/media/common/tuners/mt2266.c # >= 2.6.26 + defsnc '[ ]static[ ]u8[ ]def_regs\[\][ ]=' drivers/media/common/tuners/tda18218.c + defsnc '[ ]static[ ]unsigned[ ]char[ ]iso_regs\[8\]\[4\][ ]=' drivers/media/usb/cpia2/cpia2_usb.c + initnc '[ ][ ]u8[ ]buf,[ ]bufs\[\][ ]=' drivers/media/dvb/dvb-usb/cxusb.c + defsnc 'static[ ]struct[ ]dib0090_wbd_slope[ ]dib7090e_wbd_table\[\][ ]=' drivers/media/dvb/dvb-usb/dib0700_devices.c + defsnc '[ ][}][ ]regs\[\][ ]=' drivers/media/video/em28xx/em28xx-dvb.c + defsnc 'static[ ]u8[ ]init_code\[\]\[2\][ ]=' drivers/media/dvb/dvb-usb/friio-fe.c + defsnc 'static[ ]u8[ ]opera1_inittab\[\][ ]=' drivers/media/usb/dvb-usb/opera1.c + defsnc 'static[ ]u8[ ]s7395_inittab\[\][ ]=' drivers/media/dvb/dvb-usb/lmedm04.h + defsnc '[ ][}][ ]regs\[\][ ]=' drivers/media/video/em28xx/em28xx-dvb.c + defsnc 'static[ ]const[ ]__u8[ ]cx11646_fw1\[\]\[3\][ ]=' drivers/media/video/gspca/conex.c + defsnc 'static[ ]const[ ]__u8[ ]cx_inits_\(176\|320\|352\|640\)\[\][ ]=' drivers/media/video/gspca/conex.c + defsnc 'static[ ]const[ ]__u8[ ]cx_jpeg_init\[\]\[8\][ ]=' drivers/media/video/gspca/conex.c + defsnc 'static[ ]const[ ]__u8[ ]cxjpeg_\(640\|352\|320\|176\|qtable\)\[\]\[8\][ ]=' drivers/media/video/gspca/conex.c + defsnc 'static[ ]struct[ ]validx[ ]tbl_\(commm\?on\|init_\(at_startup\|post_alt\)\|sensor_settings_common\(_[ab]\|1\)\|big\(_[abc]\|[123]\)\|640\|800\)\[\][ ]=' 'drivers/media/video/gspca/gl860/gl860-\(mi2020\|mi1320\|ov9655\|ov2640\).c' + defsc 'static[ ]struct[ ]idxdata[ ]tbl_common\(_[a-e]\|5\|_\?3B\?\)\[\][ ]=' 'drivers/media/video/gspca/gl860/gl860-\(mi2020\|mi1320\|ov9655\|ov2640\)\.c' + defsnc 'static[ ]u8[ ][*]tbl_\(640\|800\|1280\)\[\][ ]=' 'drivers/media/video/gspca/gl860/gl860-\(mi1320\|ov9655\).c' + defsnc '[ ]struct[ ]jlj_command[ ]start_commands\[\][ ]=' drivers/media/video/gspca/jeilinj.c + defsnc 'static[ ]const[ ]u8[ ]jpeg_head\[\][ ]=' drivers/media/video/gspca/jpeg.h + defsnc '[ ][ ]\(static[ ]\)\?const[ ]struct[ ]sensor_w_data[ ]\(cif\|vga\)_sensor[01]_init_data\[\][ ]=' drivers/media/video/gspca/mr97310a.c + defsnc 'static[ ]const[ ]u8[ ]\(nw80[012]\|spacecam2\?\|cvideopro\|dlink\|ds3303\|kr651\|kritter\|mustek\|proscope\|twinkle\|dvcv6\)_start\(_\([12]\|q\?vga\)\)\?\[\][ ]=' drivers/media/video/gspca/nw80x.c + defsnc 'static[ ]const[ ]struct[ ]ov_i2c_regvals[ ]norm_7660\[\][ ]=' drivers/media/video/ov519.c + initc '[ ]\?static[ ]const[ ]struct[ ]ov_i2c_regvals[ ]norm_76[1247]0\[\][ ]=' drivers/media/video/gspca/ov519.c + defsnc '[ ]const[ ]unsigned[ ]char[ ]\(y\|uv\)QuanTable51[18]\[\][ ]=' 'drivers/media/video/\(ov511\|gspca/ov519\)\.c' + defsnc '[ ]static[ ]const[ ]struct[ ]ov_regvals[ ]bridge_ov7660\[2\]\[10\][ ]=' drivers/media/video/gspca/ov519.c + defsnc '[ ]static[ ]const[ ]u8[ ]fr_tb\[2\]\[6\]\[3\][ ]=' drivers/media/video/gspca/ov519.c + defsnc '[ ]static[ ]const[ ]struct[ ]ov_i2c_regvals[ ]\(brit\|contrast\|colors\)_7660\[\]\[\(6\|7\|31\)\][ ]=' drivers/media/video/gspca/ov519.c + defsnc 'static[ ]const[ ]u8[ ]\(bridge\|sensor\)_init\(_2\)\?\[\]\[2\][ ]=' drivers/media/video/gspca/ov534_9.c + defsnc 'static[ ]const[ ]u8[ ]\(ov965x\|ov971x\|ov562x\)_init\(_2\)\?\[\]\[2\][ ]=' drivers/media/video/gspca/ov534_9.c + defsnc 'static[ ]const[ ]u8[ ]bridge_start_\([qs]\?v\|x\)ga\[\]\[2\][ ]=' drivers/media/video/gspca/ov534_9.c + defsnc 'static[ ]const[ ]u8[ ]\(bridge\|sensor\)_init_7\(67\|72\)x\[\]\[2\][ ]=' drivers/media/video/gspca/ov534.c + defsnc '[ ]*static[ ]u8[ ]color_tb\[\]\[6\][ ]=' drivers/media/video/gspca/ov534.c + initnc 'static[ ]const[ ]__u8[ ]pac207_sensor_init\[\]\[8\][ ]=' drivers/media/video/gspca/pac207.c + defsnc 'static[ ]const[ ]u8[ ]\(start\|page3\)_7302\[\][ ]=' drivers/media/video/gspca/pac7302.c + initnc 'static[ ]const[ ]__u8[ ]pac7311_jpeg_header\[\][ ]=' drivers/media/video/gspca/pac7311.c + defsnc 'static[ ]const[ ]__u8[ ]\(start\|page[34]\)_73\(02\|11\)\[\][ ]=' drivers/media/video/gspca/pac7311.c + defsnc '[ ]struct[ ]init_command[ ]\(spy\|cif\|ms350\|genius\|vivitar\)_start_commands\[\][ ]=' drivers/media/video/gspca/sn9c2028.c + defsnc 'static[ ]const[ ]\(int\|s16\)[ ]hsv_\(red\|green\|blue\)_[xy]\[\][ ]=' drivers/media/video/gspca/sn9c20x.c + defsnc 'static[ ]const[ ]u16[ ]bridge_init\[\]\[2\][ ]=' drivers/media/video/gspca/sn9c20x.c + defsnc 'static[ ]const[ ]struct[ ]i2c_reg_u8[ ]\(soi968\|ov\(7670\|965[05]\)\|hv7131r\)_init\[\][ ]=' drivers/media/video/gspca/sn9c20x.c + defsnc 'static[ ]const[ ]struct[ ]i2c_reg_u16[ ]\(mt9v[01]1[12]\)_init\[\][ ]=' drivers/media/video/gspca/sn9c20x.c + initnc 'static[ ]const[ ]__u8[ ]init\(Hv7131\|Ov\(6650\|7630\(_3\)\?\)\|Pas\(106\|202\)\|Tas51[13]0\)\[\][ ]=' drivers/media/video/gspca/sonixb.c + initnc 'static[ ]const[ ]__u8[ ]\(hv7131\|ov\(6650\|7630\(_3\)\?\)\|pas\(106\|202\)\|tas51[13]0\)_sensor_init\(_com\)\?\[\]\[8\][ ]=' drivers/media/video/gspca/sonixb.c + defsnc 'static[ ]const[ ]u8[ ]\(adcm1700\|om6802\|po1030\)_sensor_\(init\|param1\)\[\]\[8\][ ]=' drivers/media/video/gspca/sonixj.c + defsnc 'static[ ]const[ ]u8[ ]\(gc0307\|po2030n\|soi768\)_sensor_\(init\|param1\)\[\]\[8\][ ]=' drivers/media/video/gspca/sonixj.c + defsnc 'static[ ]\(const[ ]\)\?\(__\)\?u8[ ]\(mt9v111\|sp80708\|hv7131[rd]\|mi0360b\?\|mo4000\|ov76\([36]0\|48\)\|om6802\|po1030\)_sensor_\(init\|param1\)\[\]\[8\][ ]=' drivers/media/video/gspca/sonixj.c + defsnc '[ ]static[ ]const[ ]u8[ ]probe_tb\[\]\[4\]\[8\][ ]=' drivers/media/video/gspca/sonixj.c + initnc 'static[ ]const[ ]__u16[ ]\(spca500_visual\|Clicksmart510\)_defaults\[\]\[3\][ ]=' drivers/media/video/gspca/spca500.c + initnc 'static[ ]const[ ]__u8[ ]qtable_\(creative_pccam\|kodak_ez200\|pocketdv\)\[2\]\[64\][ ]=' drivers/media/video/gspca/spca500.c + initnc 'static[ ]const[ ]__u16[ ]spca501c\?_\(\(3com\|arowana\|mysterious\)_\)\?\(init\|open\)_data\[\]\[3\][ ]=' drivers/media/video/gspca/spca501.c + defsnc 'static[ ]const[ ]\(__u16\|u8\)[ ]spca505b\?_\(init\|open\)_data\(_ccd\)\?\[\]\[3\][ ]=' drivers/media/video/gspca/spca505.c + defsnc 'static[ ]const[ ]\(__\)\?u16[ ]spca508\(cs110\|_sightcam2\?\|_vista\)\?_init_data\[\]\[[23]\][ ]=' drivers/media/video/gspca/spca508.c + defsnc 'static[ ]const[ ]struct[ ]ucbus_write_cmd[ ]\(icx098bq\|lz24bp\)_start_[012]\[\][ ]=' drivers/media/video/gspca/sq930x.c + defsnc '[}][ ]capconfig\[4\]\[2\][ ]=' drivers/media/video/gspca/sq930x.c + defsnc 'static[ ]const[ ]\(__u16\|struct[ ]cmd\)[ ]spca504\(_pccam600\|A_clicksmart420\)_\(init\|open\)_data\[\]\(\[3\]\)\?[ ]=' drivers/media/video/gspca/sunplus.c + defsnc 'static[ ]const[ ]\(__\)\?u8[ ]qtable_\(creative_pccam\|spca504_default\)\[2\]\[64\][ ]=' drivers/media/video/gspca/sunplus.c + defsnc 'static[ ]const[ ]u8[ ]n4_\(om6802\|other\|tas5130a\)\[\][ ]=' drivers/media/video/gspca/t613.c + defsnc 'static[ ]const[ ]u8[ ]n4_lt168g\[\][ ]=' drivers/media/video/gspca/t613.c + defsnc 'static[ ]const[ ]u8[ ]DQT\[17\]\[130\][ ]=' drivers/media/video/gspca/topro.c + defsnc 'static[ ]const[ ]struct[ ]cmd[ ]tp6810_late_start\[\][ ]=' drivers/media/video/gspca/topro.c + defsnc '[ ]static[ ]const[ ]struct[ ]cmd[ ]sensor_init\[\][ ]=' drivers/media/video/gspca/topro.c + defsnc '[ ]static[ ]const[ ]u8[ ]gamma_tb\[NGAMMA\]\[3\]\[1024\][ ]=' drivers/media/video/gspca/topro.c + defsnc 'static[ ]const[ ]u8[ ]eeprom_data\[\]\[3\][ ]=' drivers/media/gspca/tv8532.c + initc 'static[ ]const[ ]\(__\)\?u8[ ]\(mi\(0360\|13[12]0\)\|po\(1200\|3130\)\|hv7131r\|ov76[67]0\)_\(\(soc\)\?_\?[iI]nit\(Q\?V\|SX\)GA\(_\(JPG\|data\)\)\?\|rundata\)\[\]\[4\][ ]=\([ ][{][*][/][;]\)\?' drivers/media/video/gspca/vc032x.c + defsnc 'static[ ]const[ ]u8[ ]poxxxx_\(init\(_common\|Q\?VGA\|_end_1\|_start_3\)\|gamma\)\[\]\[4\][ ]=' drivers/media/video/gspca/vc032x.c + defsnc 'static[ ]const[ ]u16[ ]rca_initdata\[\]\[3\][ ]=' drivers/media/video/gspca/xirlink_cit.c + defsnc 'static[ ]const[ ]struct[ ]usb_action[ ]\(cs2102\|hdcs2020xx\|icm105a\(xx\)\?\|ov7630c\|mt9v111_[13]\|pb0330\([3x]x\)\?\|mi0360soc\)_Initial\(Scale\)\?\[\][ ]=' drivers/media/video/gspca/zc3xx.c + defsnc '[ ]static[ ]const[ ]u8[ ]gamma_tb\[6\]\[16\][ ]=' drivers/media/video/gspca/zc3xx.c + defsnc 'static[ ]const[ ]unsigned[ ]char[ ]hash_table_ops\[64[*]4\][ ]=' drivers/media/usb/pwc/pwc-dec23.c + defsnc 'static[ ]const[ ]unsigned[ ]int[ ]MulIdx\[16\]\[16\][ ]=' drivers/media/usb/pwc/pwc-dec23.c + defsnc 'const[ ]struct[ ]Kiara_table_entry[ ]Kiara_table\[PSZ_MAX\]\[6\]\[4\][ ]=' drivers/media/video/pwc/pwc-kiara.c + defsnc 'const[ ]unsigned[ ]int[ ]KiaraRomTable[ ]\[8\]\[2\]\[16\]\[8\][ ]=' drivers/media/video/pwc/pwc-kiara.c + defsnc 'const[ ]struct[ ]Timon_table_entry[ ]Timon_table\[PSZ_MAX\]\[PWC_FPS_MAX_TIMON\]\[4\][ ]=' drivers/media/video/pwc/pwc-timon.c + defsnc 'const[ ]unsigned[ ]int[ ]TimonRomTable[ ]\[16\]\[2\]\[16\]\[8\][ ]=' drivers/media/video/pwc/pwc-timon.c + initnc 'static[ ]const[ ]u8[ ]SN9C102_\(Y\|UV\)_QTABLE[01]\[64\][ ]=[ ][{]' drivers/media/usb/sn9c102/sn9c102_config.h + initnc '[ ]static[ ]\(const[ ]\)\?u8[ ]jpeg_header\[589\][ ]=[ ][{]' media/video/sn9c102/sn9c102_core.c + accept '[ ][ ]\?err[ ]=[ ]sn9c102_write_const_regs[(]cam\(,[ \n]\+[{]0x[0-9a-fA-F][0-9a-fA-F],[ ]0x[0-9a-fA-F][0-9a-fA-F][}]\)*[)][;]' + initnc 'static[ ]struct[ ]regval[ ]ov_initvals\[\][ ]=' drivers/media/usb/stkwebcam/stk-sensor.c + initnc 'static[ ]struct[ ]regval[ ]stk1125_initvals\[\][ ]=' drivers/media/usb/stkwebcam/stk-webcam.c + defsnc 'static[ ]u8[ ]dvbc_philips_tdm1316l_inittab\[\][ ]=' drivers/media/dvb/ttpci/budget-ci.c + defsnc '[ ]u8[ ]b\[\][ ]=' drivers/media/usb/ttusb-dec/ttusbdecfe.c + defsnc '[ ]static[ ]char[ ]init_values\[38\]\[3\][ ]=' drivers/media/video/usbvision/usbvision-core.c + defsnc 'static[ ]unsigned[ ]char[ ]header2\[\][ ]=' drivers/media/usb/zr364xx/zr364xx.c + defsnc '[ ]static[ ]const[ ]char[ ][*][ ]const[ ]vui_sar_idc\[\][ ]=' drivers/media/video/v4l2-ctrls.c + defsnc '[ ]static[ ]unsigned[ ]char[ ]static_pad\[\][ ]=' drivers/s390/crypto/zcrypt_msgtype6.c + defsnc 'static[ ]const[ ]unsigned[ ]int[ ]muxonechan\[\][ ]=' drivers/staging/comedi/drivers/adv_pci1710.c + accept '#define[ ]_MAP_0_32_ASCII_SEG7_NON_PRINTABLE[ ]\\[\n][ ]\(0,\)\+$' 'drivers/input/misc/map_to_7segment\.h\|include/linux/map_to_7segment\.h' + defsnc 'static[ ]yyconst[ ]\(flex_int\(16\|32\)_t\|\(\(short[ ]\)\?int\)\)[ ]yy_[^[]*\[[][0-9]*\][ ]=' + defsnc 'static[ ]const[ ]\(yytype_u\?int\(8\|16\)\|\(unsigned[ ]\)\?\(short\([ ]int\)\?\|char\)\)[ ]yy[^[]*\[\][ ]=' + defsnc 'static[ ]int[ ]__devinit[ ]azx_probe[(][^)]*[)][\n][{]\([\n]\+[^\n}][^\n]*\)*[^\n]*request_firmware[^\n]*' sound/pci/hda/hda_intel.c + # New in 3.7: + blobname 'imx[/]sdma[/]sdma-imx6q-to1\.bin' arch/arm/boot/dts/imx6q.dtsi + accept 'AES_T[ed]:\([\n]\.word[ ]0x[0-9a-f]*\([,][ ]0x[0-9a-f]*\)*\)*[\n][@][ ]T[ed]4\[256\]\([\n]\.byte[ ]0x[0-9a-f]*\([,][ ]0x[0-9a-f]*\)*\)*\([\n][@][ ]rcon\[\]\([\n]\.word[ ]0x[0-9a-f]*\([,][ ]0x[0-9a-f]*\)*\)*\([,][ ]0\)*\)\?' arch/arm/crypto/aes-armv4.S + defsnc 'const[ ]u32[ ]cast5_s[1234]\[256\][ ]=' crypto/cast5_generic.c + defsnc 'const[ ]u32[ ]cast6_s[1234]\[256\][ ]=' crypto/cast6_generic.c + accept '[ ][*][ ]Once[ ]it[ ]returns[ ]successfully[,][ ]driver[ ]can[ ]use[ ]request_firmware' drivers/base/firmware_class.c + accept 'int[\n ]cache_firmware[(]const[ ]char[ ][*]fw_name[)][\n][{]\([\n]\+[^\n}][^\n]*\)*ret[ ]=[ ]request_firmware[(][^\n]*\([\n]\+[^\n}][^\n]*\)*[\n]\+[}][\n]' drivers/base/firmware_class.c + accept '[ ][*][ ]If[ ]one[ ]device[ ]called[ ]request_firmware' drivers/base/firmware_class.c + defsnc 'static[ ]const[ ]struct[ ]mV_pos[ ]__cpuinitconst[ ]\(vrm85\|mobilevrm\)_mV\[32\][ ]=' drivers/cpufreq/longhaul.h + defsnc 'static[ ]const[ ]unsigned[ ]char[ ]__cpuinitconst[ ]mV_\(vrm85\|mobilevrm\)\[32\][ ]=' drivers/cpufreq/longhaul.h + # Sources for these are in the corresponding .fuc files. + defsnc 'static[ ]u32[ ]nva3_pcopy_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h + defsnc 'static[ ]u32[ ]nvc0_pcopy_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h + defsnc 'static[ ]uint32_t[ ]nv98_pcrypt_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h + defsnc 'uint32_t[ ]nve0_grgpc_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h + defsnc 'uint32_t[ ]nve0_grhub_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h + defsnc 'nv04_graph_ctx_regs\[\][ ]=' drivers/gpu/drm/nouveau/core/engine/graph/nv04.c + accept '[ ]*ret[ ]=[ ]request_firmware[(]&fw[,][ ]source[,][ ]&nv_device[(]bios[)]->pdev->dev[)][;]' drivers/gpu/drm/nouveau/core/subdev/bios/base.c + defsnc 'static[ ]u8[ ][*]edid_load[(][^)]*[)][\n][{]\([\n]\+[^\n}][^\n]*\)*[^\n]*err[ ]=[ ]request_firmware[(][&]fw[,][ ]name[,][ ][&]pdev' drivers/gpu/drm/drm_edid_load.c + defsnc 'static[ ]const[ ]RegInitializer[ ]initData\[\][ ]__initconst[ ]=' drivers/ide/ali14xx.c + defsnc 'static[ ]const[ ]struct[ ]reg_val[ ]tuner_init_fc2580\[\][ ]=' drivers/media/dvb-frontends/af9033_priv.h + defsnc '[ ]static[ ]const[ ]u8[ ]bw_params1\[3\]\[34\][ ]=' drivers/media/dvb-frontends/rtl2830.c + blobname 's5k4ecgx\.bin' drivers/media/i2c/s5k4ecgx.c + blobname 'v4l-coda\(dx6-imx27\|7541-imx53\)\.bin' drivers/media/platform/coda.c + blobname 's5p-mfc\(-v6\)\?\.fw' drivers/media/platform/s5p-mfc/s5p_mfc.c + defsnc 'static[ ]const[ ]struct[ ]e4000_lna_filter[ ]e400_lna_filter_lut\[\][ ]=' drivers/media/tuners/e4000_priv.h + defsnc 'static[ ]const[ ]struct[ ]e4000_if_filter[ ]e4000_if_filter_lut\[\][ ]=' drivers/media/tuners/e4000_priv.h + defsnc 'static[ ]const[ ]struct[ ]fc2580_reg_val[ ]fc2580_init_reg_vals\[\][ ]=' drivers/media/tuners/fc2580_priv.h + defsnc 'static[ ]const[ ]struct[ ]fc2580_freq_regs[ ]fc2580_freq_regs_lut\[\][ ]=' drivers/media/tuners/fc2580_priv.h + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm5110_revb_patch\[\][ ]=' drivers/mfd/wm5110-tables.c + defsnc 'static[ ]struct[ ]nand_ecclayout[ ]lpc32xx_nand_oob[ ]=' drivers/mtd/nand/lpc32xx_mlc.c + defsnc 'static[ ]struct[ ]nand_ecclayout[ ]flctl_4secc_oob_64[ ]=' drivers/mtd/nand/sh_flctl.c + defsnc 'static[ ]const[ ]struct[ ]atl1c_platform_patch[ ]plats\[\][ ]__devinitconst[ ]=' drivers/net/ethernet/atheros/atl1c/atl1c_main.c + defsnc 'static[ ]const[ ]u32[ ]ar9565_1p0_\(\(mac\|baseband\|radio\)_core\|[Cc]ommon_\(wo_xlna_\)\?rx_gain_table\)\[\]\[2\][ ]=' drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h + defsnc 'static[ ]const[ ]u32[ ]ar9565_1p0_\(\(mac\|baseband\)_postamble\|[Mm]odes_\(low\(est\)\?\|high\)_\(ob_db\|power\)_tx_gain_table\)\[\]\[5\][ ]=' drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h + defsnc 'static[ ]u16[ ]r2057_rev[4578]a\?_init\[[45][245]\]\[2\][ ]=' drivers/net/wireless/b43/radio_2057.c + defsnc '[ ]*tbl_rf_control_override_rev7_over[01]\[\][ ]=' drivers/net/wireless/b43/tables_nphy.c + defsnc 'static[ ]const[ ]unsigned[ ]pci_pins\[\][ ]=' drivers/pinctrl/spear/pinctrl-spear1310.c + defsnc 'static[ ]int[ ]array_soc\[\]\[2\][ ]=' drivers/power/88pm860x_battery.c + defsnc 'static[ ]const[ ]int[ ]mc13783_sw[12]x_val\[\][ ]=' drivers/regulator/mc13783-regulator.c + # remoteproc uses request_firmware, but it is generic and names + # no blobs of its own, so we change it to maybe_request_firmware. + accept '[ ]ret[ ]=[ ]request_firmware_nowait[(]THIS_MODULE[,][ ]FW_ACTION_HOTPLUG[,][\n][ ]*rproc->firmware[,][ ][&]rproc->dev[,][ ]GFP_KERNEL[,][\n][ ]*rproc[,][ ]rproc_fw_config_virtio[)][;][\n][ ]if[ ][(]ret[ ]<[ ]0[)][ ][{][\n][ ][ ]dev_err[(][&]rproc->dev[,][ ]["]request_firmware_nowait[ ]err' drivers/remoteproc/remoteproc_core.c + # This remoteproc client does name blobs, but we discard it + # with undefine_macro. + blob 'SPROC_MODEM_NAME[ ]["]-fw\.bin["]' drivers/remoteproc/ste_modem_rproc.c + accept '[ ]if[ ][(]request_firmware[(]&fw_entry,[ ]fname,[ ]&ioa_cfg->pdev->dev[)][)]' drivers/scsi/ipr.c + blobname 'daqboard2000_firmware\.bin' drivers/staging/comedi/drivers/daqboard2000.c + blobname 'me2600_firmware\.bin' drivers/staging/comedi/drivers/me_daq.c + blobname 'ni6534a\.bin' drivers/staging/comedi/drivers/ni_pcidio.c + blobname 'niscrb0[12]\.bin' drivers/staging/comedi/drivers/ni_pcidio.c + defsnc 'static[ ]const[ ]struct[ ]SiS_TVData[ ]XGI_\(St\|Ext\)\(PAL\|NTSC\|YPbPr\(525\|750\)[ip]\)Data\[\][ ]=' drivers/staging/xgifb/vb_table.h + defsnc 'static[ ]const[ ]unsigned[ ]char[ ]XGI330_\(NTSC\|PAL\|HiTV\(Ext\|St[12]\|Text\)\|YPbPr\(525\|750\)[ip]\)Timing\[\][ ]=' drivers/staging/xgifb/vb_table.h + defsnc 'static[ ]const[ ]unsigned[ ]char[ ]XGI330_\(HiTV\|Ren\(525\|750\)p\)Group3\(Data\|Simu\|Text\)\?\[\][ ]=' drivers/staging/xgifb/vb_table.h + accept 'static[ ]inline[ ]int[\n]\(maybe_\)\?reject_ihex_firmware\(_nowait\)\?[(][^{;]*[)][\n][{]\([\n]\+[^\n}][^\n]*\)*[^\n]*[\n]\+[}]' include/linux/firmware.h + defsnc '[/][*][ ]callback[ ]from[ ]request_firmware_nowait' sound/pci/hda/hda_intel.c + defsnc 'static[ ]int[ ]__devinit[ ]azx_probe[(][^)]*[)][\n][{]\([\n]\+[^\n}][^\n]*\)*[^\n]*request_firmware[^\n]*' sound/pci/hda/hda_intel.c + defsnc 'static[ ]struct[ ]reg_default[ ]da9055_reg_defaults\[\][ ]=' sound/soc/codecs/da9055.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]sta32x_regs\[\][ ]=' sound/soc/codecs/sta32x.c + blobname 'wm0010\(_stage2\.bin\|\.dfw\)' sound/soc/codecs/wm0010.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm5102_sysclk_reva_patch\[\][ ]=' sound/soc/codecs/wm5102.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm8510_reg_defaults\[\][ ]=' sound/soc/codecs/wm8510.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm8580_reg_defaults\[\][ ]=' sound/soc/codecs/wm8580.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm8776_reg_defaults\[\][ ]=' sound/soc/codecs/wm8776.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm8900_reg_defaults\[\][ ]=' sound/soc/codecs/wm8900.c + defsnc 'static[ ]const[ ]struct[ ]reg_default[ ]wm8960_reg_defaults\[\][ ]=' sound/soc/codecs/wm8960.c + accept '[ ][ ]priv->firmware[ ]=[ ]true[;]' drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c + accept '[ ][ ]*\(if[ ][(]\|[ ][ ][ ][ ]\)nvc0_graph_ctor_fw[(]priv[,][ ]["]fuc4\(09\|1a\)[cd]["][,][ ][&]priv->fuc4\(09\|1a\)[cd][)]' 'drivers/gpu/drm/nouveau/core/engine/graph/nv[ce]0\.c' + accept '[ ][ ]*nvc0_graph_dtor_fw[(]&priv->fuc4\(09\|1a\)[cd][)][;]' 'drivers/gpu/drm/nouveau/nv[ce]0\.c' + accept '[ ][ ]*nvc0_graph_init_fw[(]priv[,][ ]0x4\(09\|1a\)000[,][ ][&]priv->fuc4\(09\|1a\)c[,][ \n ]*[&]priv->fuc4\(09\|1a\)d[)][;]' 'drivers/gpu/drm/nouveau/core/engine/graph/nv[ce]0\.c' + blobname 'dvb-fe-xc5000c-4\.1\.30\.7\.fw' drivers/media/tuners/xc5000.c + accept '[ ]\.firmware[ ]=[ ]AF9015_FIRMWARE' drivers/media/usb/dvb-usb-v2/af9015.c + accept '[ ]\.firmware[ ]=[ ]AF9035_FIRMWARE' drivers/media/usb/dvb-usb-v2/af9035.c + accept '[ ]\.firmware[ ]*=[ ]AZ6007_FIRMWARE' drivers/media/usb/dvb-usb-v2/az6007.c + accept '[ ]\.firmware[ ]=[ ]EC168_FIRMWARE' drivers/media/usb/dvb-usb-v2/ec168.c + blobname 'brcm[/]brcmfmac43\(143\|242a\)\.bin' drivers/net/wireless/brcm80211/brcmfmac/usb.c + accept '[ ]priv->firmware[ ]=[ ]fw[;]' drivers/net/wireless/p54/p54pci.c + blobname 'c[bt]2\?fw-3\.1\.0\.0\.bin' drivers/scsi/bfa/bfad.c + blobname 'gdmuimg\.bin' drivers/staging/gdm72xx/usb_boot.c + blobname 'CMV4[pi]\.bin\(\.v2\)\?' drivers/usb/atm/ueagle-atm.c + blobname 'dvb-fe-tda10071\.fw' drivers/media/dvb/frontends/tda10071_priv.h + accept '[ ]st->it913x_config\.firmware[ ]=' drivers/media/usb/dvb-usb-v2/it913x.c + # Present in 3.6 but removed in the patch: + defsnc 'static[ ]const[ ]unsigned[ ]char[ ]__\(cpu\)\?initdata[ ]mV_vrm85\[32\][ ]=' arch/x86/kernel/cpu/cpufreq/longhaul.h + accept '[ ][ ]snprintf[(]fname[,][ ]sizeof[(]fname[)][,][ ]["]nouveau[/]%s["][,][ ]nouveau_vbios[)][;][\n][ ][ ]ret[ ]=[ ]request_firmware[(]' drivers/gpu/drm/nouveau/nouveau_bios.c + defsnc '\(static[ ]uint32_t\|[}]\)[ ]nv04_graph_ctx_regs[ ]\?\[\][ ]=' drivers/char/drm/nv04_graph.c + defsc 'uint32_t[ ]nv98_pcrypt_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/nv98_crypt.fuc.h + defsnc '\(uint32_t\|u32\)[ ]nva3_pcopy_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/nva3_copy.fuc.h + defsnc '\(uint32_t\|u32\)[ ]nvc0_pcopy_\(data\|code\)\[\][ ]=' drivers/gpu/drm/nouveau/nvc0_copy.fuc.h + accept '[ ]it913x_config\.firmware[ ]=[ ]' drivers/media/dvb/dvb-usb/it913x.c + accept '[ ]*props->firmware[ ]=[ ]fw_it913\(5_v[12]\|7\)' drivers/media/dvb/dvb-usb/it913x.c + defsnc '[ ]static[ ]const[ ]u8[ ]rsshash\[40\][ ]=' drivers/net/igb/igb_main.c + accept '[ ]hif_dev->firmware[ ]=[ ]fw[;]' drivers/net/wireless/ath/ath9k/hif_usb.c + accept '[ ]hif_dev->firmware[ ]=[ ]NULL[;]' drivers/net/wireless/ath/ath9k/hif_usb.c + defsnc 'static[ ]const[ ]unsigned[ ]\(rgmii\|smii_0_1_2\|nand_8bit\|mcif\|pci_sata\|clcd\|arm_trace\|miphy_dbg\|emi\)_pins\[\][ ]=' drivers/pinctrl/spear/pinctrl-spear1310.c + accept '[ ]ret[ ]=[ ]request_firmware\([(][&]firmware_p[,][ ]rproc->firmware[,][ ]dev[)]\|_nowait[(]THIS_MODULE[,][ ]FW_ACTION_HOTPLUG[,][\n][ ]*rproc->firmware[,][ ]dev[,][ ]GFP_KERNEL[,][\n][ ]*rproc[,][ ]rproc_fw_config_virtio[)]\)[;][\n][ ]if[ ][(]ret[ ]<[ ]0[)][ ][{][\n][ ][ ]dev_err[(]dev[,][ ]["]request_firmware\(_nowait\)\?[ ]failed' drivers/remoteproc/remoteproc_core.c + accept '[ ]if[(]request_firmware[(]&fw_entry,[ ]fname,[ ]&ioa_cfg->pdev->dev[)][)]' drivers/scsi/ipr.c + defsnc 'const[ ]unsigned[ ]char[ ]map_table\[\][ ]=' drivers/staging/lirc/lirc_ttusbir.c + defsnc 'static[ ]struct[ ]SiS_\(LCD\|LVDS\)Data[ ][ ]*XGI_\(\(\(St\|Ext\)LCD\|LVDS\)\(1024x768\|1280x1024\|1400x1050\)\|NoScaling\)Data\(_[12]\)\?\[\][ ]=' drivers/staging/xgifb/vb_table.h + accept '[ ]if[ ][(][/][*]KEYSPAN_PDA[*][/]request_ihex_firmware' drivers/usb/serial/keyspan_pda.c + defsnc 'static[ ]const[ ]u8[ ]sta32x_regs\[STA32X_REGISTER_COUNT\][ ]=' sound/soc/codecs/sta32x.c + defsnc 'static[ ]const[ ]u16[ ]wm8510_reg\[WM8510_CACHEREGNUM\][ ]=' sound/soc/codecs/wm8510.c + defsnc 'static[ ]const[ ]u16[ ]wm8900_reg_defaults\[WM8900_MAXREG\][ ]=' sound/soc/wm8900.c + defsnc 'static[ ]const[ ]u16[ ]wm8960_reg\[WM8960_CACHEREGNUM\][ ]=' sound/soc/codecs/wm8960.c + # Specific for the 3.7-to-3.6 reverse patch: + accept '[ ]err[ ]=[ ]request_firmware[(]&fw,[ ]patch,[ ]dev[)][;]' sound/pci/hda/hda_hwdep.c + defsnc '\(static[ ]const[ ]struct[ ]\(stk1160\|saa7113\)config\|[}]\)[ ]\(stk1160\|saa7113\)config\(PAL\|NTSC\)\?\[\(256\)\?\][ ]=' drivers/staging/easycap/easycap_low.c + accept '[ ]kernel[(]driver[)]:[ ]calls[ ]request_firmware[(]' Documentation/firmware_class/README + accept '[ ]kernel:[ ]request_firmware[(]' Documentation/firmware_class/README + accept '[ ][ ]\.firmware[ ]*=[ ]["][/][*][(]DEBLOBBED[)][*][/]["]' + accept '[;][/][*]@@[ ]-418,45[ ][+]446,68[ ]@@[*][/][;][\n]\([ ]*[2],\)*[\n]\(\([ ]*[1-4],\)*[\n]\)*\([ ]*[ 1][0-9],\)*[ ]*12' scripts/dtc/dtc-parser.tab.c_shipped ;; */patch-3.5*) diff --git a/freed-ora/current/f18/deblob-main b/freed-ora/current/f18/deblob-main index 63d0c9325..3a85cdc96 100755 --- a/freed-ora/current/f18/deblob-main +++ b/freed-ora/current/f18/deblob-main @@ -271,35 +271,35 @@ xdelta3 -e -9 -S djw -s linux-$kver.tar linux-libre-$kver-$gnu.tar linux-libre-$ echo Creating xdelta between linux-$kver.tar and linux-libre-$kver-$gnu.tar xdelta delta -0 linux-$kver.tar linux-libre-$kver-$gnu.tar linux-libre-$kver-$gnu.xdelta || : # xdelta returns nonzero on success +cleanup="linux-libre-$kver-$gnu.tar linux-libre-$kver-$gnu.vcdiff linux-libre-$kver-$gnu.xdelta" + echo Compressing binary deltas and linux-libre-$kver-$gnu.tar rm -f linux-$kver.tar if test -f linux-libre-$kver-$gnu.vcdiff; then bzip2 -k9 linux-libre-$kver-$gnu.vcdiff xz -k9 linux-libre-$kver-$gnu.vcdiff || : lzip -k9 linux-libre-$kver-$gnu.vcdiff || : - rm -f linux-libre-$kver-$gnu.vcdiff fi if test -f linux-libre-$kver-$gnu.xdelta; then bzip2 -k9 linux-libre-$kver-$gnu.xdelta xz -k9 linux-libre-$kver-$gnu.xdelta || : lzip -k9 linux-libre-$kver-$gnu.xdelta || : - rm -f linux-libre-$kver-$gnu.xdelta fi bzip2 -k9 linux-libre-$kver-$gnu.tar xz -k9 linux-libre-$kver-$gnu.tar || : lzip -k9 linux-libre-$kver-$gnu.tar || : -cleanup=linux-libre-$kver-$gnu.tar - echo Done except for signing, feel free to interrupt for f in \ linux-libre-$kver-$gnu.tar \ linux-libre-$kver-$gnu.tar.bz2 \ linux-libre-$kver-$gnu.tar.xz \ linux-libre-$kver-$gnu.tar.lz \ + linux-libre-$kver-$gnu.vcdiff \ linux-libre-$kver-$gnu.vcdiff.bz2 \ linux-libre-$kver-$gnu.vcdiff.xz \ linux-libre-$kver-$gnu.vcdiff.lz \ + linux-libre-$kver-$gnu.xdelta \ linux-libre-$kver-$gnu.xdelta.bz2 \ linux-libre-$kver-$gnu.xdelta.xz \ linux-libre-$kver-$gnu.xdelta.lz \ @@ -310,8 +310,7 @@ for f in \ fi done -rm -f linux-libre-$kver-$gnu.tar - +rm -f $cleanup cleanup= trap 'status=$?; (exit $status); exit' 0 1 2 15 diff --git a/freed-ora/current/f18/efivarfs-3.7.patch b/freed-ora/current/f18/efivarfs-3.7.patch new file mode 100644 index 000000000..300910716 --- /dev/null +++ b/freed-ora/current/f18/efivarfs-3.7.patch @@ -0,0 +1,1630 @@ +From cb6f23ee9601297c3c70d0cfe3d77dfde9bd119d Mon Sep 17 00:00:00 2001 +From: Matthew Garrett <mjg@redhat.com> +Date: Fri, 5 Oct 2012 13:54:56 +0800 +Subject: [PATCH 01/17] efi: Add support for a UEFI variable filesystem + +The existing EFI variables code only supports variables of up to 1024 +bytes. This limitation existed in version 0.99 of the EFI specification, +but was removed before any full releases. Since variables can now be +larger than a single page, sysfs isn't the best interface for this. So, +instead, let's add a filesystem. Variables can be read, written and +created, with the first 4 bytes of each variable representing its UEFI +attributes. The create() method doesn't actually commit to flash since +zero-length variables can't exist per-spec. + +Updates from Jeremy Kerr <jeremy.kerr@canonical.com>. + +Signed-off-by: Matthew Garrett <mjg@redhat.com> +Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 384 ++++++++++++++++++++++++++++++++++++++++++++- + include/linux/efi.h | 5 + + 2 files changed, 383 insertions(+), 6 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index d10c987..b605c48 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -80,6 +80,10 @@ + #include <linux/slab.h> + #include <linux/pstore.h> + ++#include <linux/fs.h> ++#include <linux/ramfs.h> ++#include <linux/pagemap.h> ++ + #include <asm/uaccess.h> + + #define EFIVARS_VERSION "0.08" +@@ -91,6 +95,7 @@ MODULE_LICENSE("GPL"); + MODULE_VERSION(EFIVARS_VERSION); + + #define DUMP_NAME_LEN 52 ++#define GUID_LEN 37 + + /* + * The maximum size of VariableName + Data = 1024 +@@ -108,7 +113,6 @@ struct efi_variable { + __u32 Attributes; + } __attribute__((packed)); + +- + struct efivar_entry { + struct efivars *efivars; + struct efi_variable var; +@@ -122,6 +126,9 @@ struct efivar_attribute { + ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count); + }; + ++static struct efivars __efivars; ++static struct efivar_operations ops; ++ + #define PSTORE_EFI_ATTRIBUTES \ + (EFI_VARIABLE_NON_VOLATILE | \ + EFI_VARIABLE_BOOTSERVICE_ACCESS | \ +@@ -629,14 +636,380 @@ static struct kobj_type efivar_ktype = { + .default_attrs = def_attrs, + }; + +-static struct pstore_info efi_pstore_info; +- + static inline void + efivar_unregister(struct efivar_entry *var) + { + kobject_put(&var->kobj); + } + ++static int efivarfs_file_open(struct inode *inode, struct file *file) ++{ ++ file->private_data = inode->i_private; ++ return 0; ++} ++ ++static ssize_t efivarfs_file_write(struct file *file, ++ const char __user *userbuf, size_t count, loff_t *ppos) ++{ ++ struct efivar_entry *var = file->private_data; ++ struct efivars *efivars; ++ efi_status_t status; ++ void *data; ++ u32 attributes; ++ struct inode *inode = file->f_mapping->host; ++ int datasize = count - sizeof(attributes); ++ ++ if (count < sizeof(attributes)) ++ return -EINVAL; ++ ++ data = kmalloc(datasize, GFP_KERNEL); ++ ++ if (!data) ++ return -ENOMEM; ++ ++ efivars = var->efivars; ++ ++ if (copy_from_user(&attributes, userbuf, sizeof(attributes))) { ++ count = -EFAULT; ++ goto out; ++ } ++ ++ if (attributes & ~(EFI_VARIABLE_MASK)) { ++ count = -EINVAL; ++ goto out; ++ } ++ ++ if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) { ++ count = -EFAULT; ++ goto out; ++ } ++ ++ if (validate_var(&var->var, data, datasize) == false) { ++ count = -EINVAL; ++ goto out; ++ } ++ ++ status = efivars->ops->set_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ attributes, datasize, ++ data); ++ ++ switch (status) { ++ case EFI_SUCCESS: ++ mutex_lock(&inode->i_mutex); ++ i_size_write(inode, count); ++ mutex_unlock(&inode->i_mutex); ++ break; ++ case EFI_INVALID_PARAMETER: ++ count = -EINVAL; ++ break; ++ case EFI_OUT_OF_RESOURCES: ++ count = -ENOSPC; ++ break; ++ case EFI_DEVICE_ERROR: ++ count = -EIO; ++ break; ++ case EFI_WRITE_PROTECTED: ++ count = -EROFS; ++ break; ++ case EFI_SECURITY_VIOLATION: ++ count = -EACCES; ++ break; ++ case EFI_NOT_FOUND: ++ count = -ENOENT; ++ break; ++ default: ++ count = -EINVAL; ++ break; ++ } ++out: ++ kfree(data); ++ ++ return count; ++} ++ ++static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, ++ size_t count, loff_t *ppos) ++{ ++ struct efivar_entry *var = file->private_data; ++ struct efivars *efivars = var->efivars; ++ efi_status_t status; ++ unsigned long datasize = 0; ++ u32 attributes; ++ void *data; ++ ssize_t size; ++ ++ status = efivars->ops->get_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ &attributes, &datasize, NULL); ++ ++ if (status != EFI_BUFFER_TOO_SMALL) ++ return 0; ++ ++ data = kmalloc(datasize + 4, GFP_KERNEL); ++ ++ if (!data) ++ return 0; ++ ++ status = efivars->ops->get_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ &attributes, &datasize, ++ (data + 4)); ++ ++ if (status != EFI_SUCCESS) ++ return 0; ++ ++ memcpy(data, &attributes, 4); ++ size = simple_read_from_buffer(userbuf, count, ppos, ++ data, datasize + 4); ++ kfree(data); ++ ++ return size; ++} ++ ++static void efivarfs_evict_inode(struct inode *inode) ++{ ++ clear_inode(inode); ++} ++ ++static const struct super_operations efivarfs_ops = { ++ .statfs = simple_statfs, ++ .drop_inode = generic_delete_inode, ++ .evict_inode = efivarfs_evict_inode, ++ .show_options = generic_show_options, ++}; ++ ++static struct super_block *efivarfs_sb; ++ ++static const struct inode_operations efivarfs_dir_inode_operations; ++ ++static const struct file_operations efivarfs_file_operations = { ++ .open = efivarfs_file_open, ++ .read = efivarfs_file_read, ++ .write = efivarfs_file_write, ++ .llseek = no_llseek, ++}; ++ ++static struct inode *efivarfs_get_inode(struct super_block *sb, ++ const struct inode *dir, int mode, dev_t dev) ++{ ++ struct inode *inode = new_inode(sb); ++ ++ if (inode) { ++ inode->i_ino = get_next_ino(); ++ inode->i_uid = inode->i_gid = 0; ++ inode->i_mode = mode; ++ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; ++ switch (mode & S_IFMT) { ++ case S_IFREG: ++ inode->i_fop = &efivarfs_file_operations; ++ break; ++ case S_IFDIR: ++ inode->i_op = &efivarfs_dir_inode_operations; ++ inode->i_fop = &simple_dir_operations; ++ inc_nlink(inode); ++ break; ++ } ++ } ++ return inode; ++} ++ ++static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid) ++{ ++ guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]); ++ guid->b[1] = hex_to_bin(str[4]) << 4 | hex_to_bin(str[5]); ++ guid->b[2] = hex_to_bin(str[2]) << 4 | hex_to_bin(str[3]); ++ guid->b[3] = hex_to_bin(str[0]) << 4 | hex_to_bin(str[1]); ++ guid->b[4] = hex_to_bin(str[11]) << 4 | hex_to_bin(str[12]); ++ guid->b[5] = hex_to_bin(str[9]) << 4 | hex_to_bin(str[10]); ++ guid->b[6] = hex_to_bin(str[16]) << 4 | hex_to_bin(str[17]); ++ guid->b[7] = hex_to_bin(str[14]) << 4 | hex_to_bin(str[15]); ++ guid->b[8] = hex_to_bin(str[19]) << 4 | hex_to_bin(str[20]); ++ guid->b[9] = hex_to_bin(str[21]) << 4 | hex_to_bin(str[22]); ++ guid->b[10] = hex_to_bin(str[24]) << 4 | hex_to_bin(str[25]); ++ guid->b[11] = hex_to_bin(str[26]) << 4 | hex_to_bin(str[27]); ++ guid->b[12] = hex_to_bin(str[28]) << 4 | hex_to_bin(str[29]); ++ guid->b[13] = hex_to_bin(str[30]) << 4 | hex_to_bin(str[31]); ++ guid->b[14] = hex_to_bin(str[32]) << 4 | hex_to_bin(str[33]); ++ guid->b[15] = hex_to_bin(str[34]) << 4 | hex_to_bin(str[35]); ++} ++ ++static int efivarfs_create(struct inode *dir, struct dentry *dentry, ++ umode_t mode, bool excl) ++{ ++ struct inode *inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); ++ struct efivars *efivars = &__efivars; ++ struct efivar_entry *var; ++ int namelen, i = 0, err = 0; ++ ++ if (dentry->d_name.len < 38) ++ return -EINVAL; ++ ++ if (!inode) ++ return -ENOSPC; ++ ++ var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); ++ ++ if (!var) ++ return -ENOMEM; ++ ++ namelen = dentry->d_name.len - GUID_LEN; ++ ++ efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1, ++ &var->var.VendorGuid); ++ ++ for (i = 0; i < namelen; i++) ++ var->var.VariableName[i] = dentry->d_name.name[i]; ++ ++ var->var.VariableName[i] = '\0'; ++ ++ inode->i_private = var; ++ var->efivars = efivars; ++ var->kobj.kset = efivars->kset; ++ ++ err = kobject_init_and_add(&var->kobj, &efivar_ktype, NULL, "%s", ++ dentry->d_name.name); ++ if (err) ++ goto out; ++ ++ kobject_uevent(&var->kobj, KOBJ_ADD); ++ spin_lock(&efivars->lock); ++ list_add(&var->list, &efivars->list); ++ spin_unlock(&efivars->lock); ++ d_instantiate(dentry, inode); ++ dget(dentry); ++out: ++ if (err) ++ kfree(var); ++ return err; ++} ++ ++static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) ++{ ++ struct efivar_entry *var = dentry->d_inode->i_private; ++ struct efivars *efivars = var->efivars; ++ efi_status_t status; ++ ++ spin_lock(&efivars->lock); ++ ++ status = efivars->ops->set_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ 0, 0, NULL); ++ ++ if (status == EFI_SUCCESS || status == EFI_NOT_FOUND) { ++ list_del(&var->list); ++ spin_unlock(&efivars->lock); ++ efivar_unregister(var); ++ drop_nlink(dir); ++ dput(dentry); ++ return 0; ++ } ++ ++ spin_unlock(&efivars->lock); ++ return -EINVAL; ++}; ++ ++int efivarfs_fill_super(struct super_block *sb, void *data, int silent) ++{ ++ struct inode *inode = NULL; ++ struct dentry *root; ++ struct efivar_entry *entry, *n; ++ struct efivars *efivars = &__efivars; ++ int err; ++ ++ efivarfs_sb = sb; ++ ++ sb->s_maxbytes = MAX_LFS_FILESIZE; ++ sb->s_blocksize = PAGE_CACHE_SIZE; ++ sb->s_blocksize_bits = PAGE_CACHE_SHIFT; ++ sb->s_magic = PSTOREFS_MAGIC; ++ sb->s_op = &efivarfs_ops; ++ sb->s_time_gran = 1; ++ ++ inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0); ++ if (!inode) { ++ err = -ENOMEM; ++ goto fail; ++ } ++ inode->i_op = &efivarfs_dir_inode_operations; ++ ++ root = d_make_root(inode); ++ sb->s_root = root; ++ if (!root) { ++ err = -ENOMEM; ++ goto fail; ++ } ++ ++ list_for_each_entry_safe(entry, n, &efivars->list, list) { ++ struct inode *inode; ++ struct dentry *dentry, *root = efivarfs_sb->s_root; ++ char *name; ++ unsigned long size = 0; ++ int len, i; ++ ++ len = utf16_strlen(entry->var.VariableName); ++ ++ /* GUID plus trailing NULL */ ++ name = kmalloc(len + 38, GFP_ATOMIC); ++ ++ for (i = 0; i < len; i++) ++ name[i] = entry->var.VariableName[i] & 0xFF; ++ ++ name[len] = '-'; ++ ++ efi_guid_unparse(&entry->var.VendorGuid, name + len + 1); ++ ++ name[len+GUID_LEN] = '\0'; ++ ++ inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, ++ S_IFREG | 0644, 0); ++ dentry = d_alloc_name(root, name); ++ ++ efivars->ops->get_variable(entry->var.VariableName, ++ &entry->var.VendorGuid, ++ &entry->var.Attributes, ++ &size, ++ NULL); ++ ++ mutex_lock(&inode->i_mutex); ++ inode->i_private = entry; ++ i_size_write(inode, size+4); ++ mutex_unlock(&inode->i_mutex); ++ d_add(dentry, inode); ++ } ++ ++ return 0; ++fail: ++ iput(inode); ++ return err; ++} ++ ++static struct dentry *efivarfs_mount(struct file_system_type *fs_type, ++ int flags, const char *dev_name, void *data) ++{ ++ return mount_single(fs_type, flags, data, efivarfs_fill_super); ++} ++ ++static void efivarfs_kill_sb(struct super_block *sb) ++{ ++ kill_litter_super(sb); ++ efivarfs_sb = NULL; ++} ++ ++static struct file_system_type efivarfs_type = { ++ .name = "efivarfs", ++ .mount = efivarfs_mount, ++ .kill_sb = efivarfs_kill_sb, ++}; ++ ++static const struct inode_operations efivarfs_dir_inode_operations = { ++ .lookup = simple_lookup, ++ .unlink = efivarfs_unlink, ++ .create = efivarfs_create, ++}; ++ ++static struct pstore_info efi_pstore_info; ++ + #ifdef CONFIG_PSTORE + + static int efi_pstore_open(struct pstore_info *psi) +@@ -1198,6 +1571,8 @@ int register_efivars(struct efivars *efivars, + pstore_register(&efivars->efi_pstore_info); + } + ++ register_filesystem(&efivarfs_type); ++ + out: + kfree(variable_name); + +@@ -1205,9 +1580,6 @@ out: + } + EXPORT_SYMBOL_GPL(register_efivars); + +-static struct efivars __efivars; +-static struct efivar_operations ops; +- + /* + * For now we register the efi subsystem with the firmware subsystem + * and the vars subsystem with the efi subsystem. In the future, it +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 8670eb1..b2af157 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -29,7 +29,12 @@ + #define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1))) + #define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1))) + #define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_NOT_READY ( 6 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_DEVICE_ERROR ( 7 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1))) + #define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_SECURITY_VIOLATION (26 | (1UL << (BITS_PER_LONG-1))) + + typedef unsigned long efi_status_t; + typedef u8 efi_bool_t; +-- +1.7.12.1 + + +From 2fc1dc88e97665c70f203f0132232ea55e8dd7eb Mon Sep 17 00:00:00 2001 +From: Jeremy Kerr <jeremy.kerr@canonical.com> +Date: Fri, 5 Oct 2012 13:54:56 +0800 +Subject: [PATCH 02/17] efi: Handle deletions and size changes in + efivarfs_write_file + +A write to an efivarfs file will not always result in a variable of +'count' size after the EFI SetVariable() call. We may have appended to +the existing data (ie, with the EFI_VARIABLE_APPEND_WRITE attribute), or +even have deleted the variable (with an authenticated variable update, +with a zero datasize). + +This change re-reads the updated variable from firmware, to check for +size changes and deletions. In the latter case, we need to drop the +dentry. + +Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 49 ++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 39 insertions(+), 10 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index b605c48..d7658b4 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -658,6 +658,7 @@ static ssize_t efivarfs_file_write(struct file *file, + u32 attributes; + struct inode *inode = file->f_mapping->host; + int datasize = count - sizeof(attributes); ++ unsigned long newdatasize; + + if (count < sizeof(attributes)) + return -EINVAL; +@@ -696,32 +697,60 @@ static ssize_t efivarfs_file_write(struct file *file, + + switch (status) { + case EFI_SUCCESS: +- mutex_lock(&inode->i_mutex); +- i_size_write(inode, count); +- mutex_unlock(&inode->i_mutex); + break; + case EFI_INVALID_PARAMETER: + count = -EINVAL; +- break; ++ goto out; + case EFI_OUT_OF_RESOURCES: + count = -ENOSPC; +- break; ++ goto out; + case EFI_DEVICE_ERROR: + count = -EIO; +- break; ++ goto out; + case EFI_WRITE_PROTECTED: + count = -EROFS; +- break; ++ goto out; + case EFI_SECURITY_VIOLATION: + count = -EACCES; +- break; ++ goto out; + case EFI_NOT_FOUND: + count = -ENOENT; +- break; ++ goto out; + default: + count = -EINVAL; +- break; ++ goto out; + } ++ ++ /* ++ * Writing to the variable may have caused a change in size (which ++ * could either be an append or an overwrite), or the variable to be ++ * deleted. Perform a GetVariable() so we can tell what actually ++ * happened. ++ */ ++ newdatasize = 0; ++ status = efivars->ops->get_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ NULL, &newdatasize, ++ NULL); ++ ++ if (status == EFI_BUFFER_TOO_SMALL) { ++ mutex_lock(&inode->i_mutex); ++ i_size_write(inode, newdatasize + sizeof(attributes)); ++ mutex_unlock(&inode->i_mutex); ++ ++ } else if (status == EFI_NOT_FOUND) { ++ spin_lock(&efivars->lock); ++ list_del(&var->list); ++ spin_unlock(&efivars->lock); ++ efivar_unregister(var); ++ drop_nlink(inode); ++ dput(file->f_dentry); ++ ++ } else { ++ pr_warn("efivarfs: inconsistent EFI variable implementation? " ++ "status = %lx\n", status); ++ } ++ + out: + kfree(data); + +-- +1.7.12.1 + + +From c98611fc95672862950c9bc4d6a3a4c4453a3c3e Mon Sep 17 00:00:00 2001 +From: "Lee, Chun-Yi" <joeyli.kernel@gmail.com> +Date: Fri, 5 Oct 2012 13:54:56 +0800 +Subject: [PATCH 03/17] efi: add efivars kobject to efi sysfs folder + +UEFI variable filesystem need a new mount point, so this patch add +efivars kobject to efi_kobj for create a /sys/firmware/efi/efivars +folder. + +Cc: Matthew Garrett <mjg@redhat.com> +Cc: H. Peter Anvin <hpa@zytor.com> +Signed-off-by: Lee, Chun-Yi <jlee@suse.com> +Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 9 +++++++++ + include/linux/efi.h | 1 + + 2 files changed, 10 insertions(+) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index d7658b4..6793965 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -1527,6 +1527,7 @@ void unregister_efivars(struct efivars *efivars) + sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var); + kfree(efivars->new_var); + kfree(efivars->del_var); ++ kobject_put(efivars->kobject); + kset_unregister(efivars->kset); + } + EXPORT_SYMBOL_GPL(unregister_efivars); +@@ -1558,6 +1559,14 @@ int register_efivars(struct efivars *efivars, + goto out; + } + ++ efivars->kobject = kobject_create_and_add("efivars", parent_kobj); ++ if (!efivars->kobject) { ++ pr_err("efivars: Subsystem registration failed.\n"); ++ error = -ENOMEM; ++ kset_unregister(efivars->kset); ++ goto out; ++ } ++ + /* + * Per EFI spec, the maximum storage allocated for both + * the variable name and variable data is 1024 bytes. +diff --git a/include/linux/efi.h b/include/linux/efi.h +index b2af157..337aefb 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -662,6 +662,7 @@ struct efivars { + spinlock_t lock; + struct list_head list; + struct kset *kset; ++ struct kobject *kobject; + struct bin_attribute *new_var, *del_var; + const struct efivar_operations *ops; + struct efivar_entry *walk_entry; +-- +1.7.12.1 + + +From 8ef5f49da57087022f2031820ceb3b1c6101d76c Mon Sep 17 00:00:00 2001 +From: Matt Fleming <matt.fleming@intel.com> +Date: Thu, 4 Oct 2012 09:57:31 +0100 +Subject: [PATCH 04/17] efivarfs: Add documentation for the EFI variable + filesystem + +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + Documentation/filesystems/00-INDEX | 2 ++ + Documentation/filesystems/efivarfs.txt | 16 ++++++++++++++++ + 2 files changed, 18 insertions(+) + create mode 100644 Documentation/filesystems/efivarfs.txt + +diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX +index 8c624a1..7b52ba7 100644 +--- a/Documentation/filesystems/00-INDEX ++++ b/Documentation/filesystems/00-INDEX +@@ -38,6 +38,8 @@ dnotify_test.c + - example program for dnotify + ecryptfs.txt + - docs on eCryptfs: stacked cryptographic filesystem for Linux. ++efivarfs.txt ++ - info for the efivarfs filesystem. + exofs.txt + - info, usage, mount options, design about EXOFS. + ext2.txt +diff --git a/Documentation/filesystems/efivarfs.txt b/Documentation/filesystems/efivarfs.txt +new file mode 100644 +index 0000000..c477af0 +--- /dev/null ++++ b/Documentation/filesystems/efivarfs.txt +@@ -0,0 +1,16 @@ ++ ++efivarfs - a (U)EFI variable filesystem ++ ++The efivarfs filesystem was created to address the shortcomings of ++using entries in sysfs to maintain EFI variables. The old sysfs EFI ++variables code only supported variables of up to 1024 bytes. This ++limitation existed in version 0.99 of the EFI specification, but was ++removed before any full releases. Since variables can now be larger ++than a single page, sysfs isn't the best interface for this. ++ ++Variables can be created, deleted and modified with the efivarfs ++filesystem. ++ ++efivarfs is typically mounted like this, ++ ++ mount -t efivarfs none /sys/firmware/efi/efivars +-- +1.7.12.1 + + +From f69c39248e2f1eebf24f5ee55139602c56d15aec Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft <apw@canonical.com> +Date: Thu, 11 Oct 2012 11:32:17 +0100 +Subject: [PATCH 05/17] efivarfs: efivarfs_file_read ensure we free data in + error paths + +Signed-off-by: Andy Whitcroft <apw@canonical.com> +Acked-by: Matthew Garrett <mjg@redhat.com> +Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 6793965..b7c9a32 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -766,7 +766,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + unsigned long datasize = 0; + u32 attributes; + void *data; +- ssize_t size; ++ ssize_t size = 0; + + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, +@@ -784,13 +784,13 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + &var->var.VendorGuid, + &attributes, &datasize, + (data + 4)); +- + if (status != EFI_SUCCESS) +- return 0; ++ goto out_free; + + memcpy(data, &attributes, 4); + size = simple_read_from_buffer(userbuf, count, ppos, + data, datasize + 4); ++out_free: + kfree(data); + + return size; +-- +1.7.12.1 + + +From 429136e16c7c43bbebb8b8030203161a2d3fc3ce Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft <apw@canonical.com> +Date: Thu, 11 Oct 2012 11:32:18 +0100 +Subject: [PATCH 06/17] efivarfs: efivarfs_create() ensure we drop our + reference on inode on error + +Signed-off-by: Andy Whitcroft <apw@canonical.com> +Acked-by: Matthew Garrett <mjg@redhat.com> +Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index b7c9a32..6e5f367 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -866,7 +866,7 @@ static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid) + static int efivarfs_create(struct inode *dir, struct dentry *dentry, + umode_t mode, bool excl) + { +- struct inode *inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); ++ struct inode *inode; + struct efivars *efivars = &__efivars; + struct efivar_entry *var; + int namelen, i = 0, err = 0; +@@ -874,13 +874,15 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + if (dentry->d_name.len < 38) + return -EINVAL; + ++ inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); + if (!inode) + return -ENOSPC; + + var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); +- +- if (!var) +- return -ENOMEM; ++ if (!var) { ++ err = -ENOMEM; ++ goto out; ++ } + + namelen = dentry->d_name.len - GUID_LEN; + +@@ -908,8 +910,10 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + d_instantiate(dentry, inode); + dget(dentry); + out: +- if (err) ++ if (err) { + kfree(var); ++ iput(inode); ++ } + return err; + } + +-- +1.7.12.1 + + +From 1a19268e8a4bae43c1feb3f71ee468c6bc70aca6 Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft <apw@canonical.com> +Date: Thu, 11 Oct 2012 11:32:19 +0100 +Subject: [PATCH 07/17] efivarfs: efivarfs_fill_super() fix inode reference + counts + +When d_make_root() fails it will automatically drop the reference +on the root inode. We should not be doing so as well. + +Signed-off-by: Andy Whitcroft <apw@canonical.com> +Acked-by: Matthew Garrett <mjg@redhat.com> +Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 16 ++++------------ + 1 file changed, 4 insertions(+), 12 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 6e5f367..adfc486 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -948,7 +948,6 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + struct dentry *root; + struct efivar_entry *entry, *n; + struct efivars *efivars = &__efivars; +- int err; + + efivarfs_sb = sb; + +@@ -960,18 +959,14 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + sb->s_time_gran = 1; + + inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0); +- if (!inode) { +- err = -ENOMEM; +- goto fail; +- } ++ if (!inode) ++ return -ENOMEM; + inode->i_op = &efivarfs_dir_inode_operations; + + root = d_make_root(inode); + sb->s_root = root; +- if (!root) { +- err = -ENOMEM; +- goto fail; +- } ++ if (!root) ++ return -ENOMEM; + + list_for_each_entry_safe(entry, n, &efivars->list, list) { + struct inode *inode; +@@ -1012,9 +1007,6 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + } + + return 0; +-fail: +- iput(inode); +- return err; + } + + static struct dentry *efivarfs_mount(struct file_system_type *fs_type, +-- +1.7.12.1 + + +From f0d90a4024493aed6fc77ce5cd3b93f278fed9c0 Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft <apw@canonical.com> +Date: Thu, 11 Oct 2012 11:32:20 +0100 +Subject: [PATCH 08/17] efivarfs: efivarfs_fill_super() ensure we free our + temporary name + +d_alloc_name() copies the passed name to new storage, once complete we +no longer need our name. + +Signed-off-by: Andy Whitcroft <apw@canonical.com> +Acked-by: Matthew Garrett <mjg@redhat.com> +Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index adfc486..36b3dd6 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -992,6 +992,8 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, + S_IFREG | 0644, 0); + dentry = d_alloc_name(root, name); ++ /* copied by the above to local storage in the dentry. */ ++ kfree(name); + + efivars->ops->get_variable(entry->var.VariableName, + &entry->var.VendorGuid, +-- +1.7.12.1 + + +From c4cf244c318218153200d0011d8ef0ebcf3146ea Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft <apw@canonical.com> +Date: Thu, 11 Oct 2012 11:32:21 +0100 +Subject: [PATCH 09/17] efivarfs: efivarfs_fill_super() ensure we clean up + correctly on error + +Ensure we free both the name and inode on error when building the +individual variables. + +Signed-off-by: Andy Whitcroft <apw@canonical.com> +Acked-by: Matthew Garrett <mjg@redhat.com> +Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 36b3dd6..216086d 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -948,6 +948,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + struct dentry *root; + struct efivar_entry *entry, *n; + struct efivars *efivars = &__efivars; ++ char *name; + + efivarfs_sb = sb; + +@@ -969,16 +970,18 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + return -ENOMEM; + + list_for_each_entry_safe(entry, n, &efivars->list, list) { +- struct inode *inode; + struct dentry *dentry, *root = efivarfs_sb->s_root; +- char *name; + unsigned long size = 0; + int len, i; + ++ inode = NULL; ++ + len = utf16_strlen(entry->var.VariableName); + + /* GUID plus trailing NULL */ + name = kmalloc(len + 38, GFP_ATOMIC); ++ if (!name) ++ goto fail; + + for (i = 0; i < len; i++) + name[i] = entry->var.VariableName[i] & 0xFF; +@@ -991,7 +994,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + + inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, + S_IFREG | 0644, 0); ++ if (!inode) ++ goto fail_name; ++ + dentry = d_alloc_name(root, name); ++ if (!dentry) ++ goto fail_inode; ++ + /* copied by the above to local storage in the dentry. */ + kfree(name); + +@@ -1009,6 +1018,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + } + + return 0; ++ ++fail_inode: ++ iput(inode); ++fail_name: ++ kfree(name); ++fail: ++ return -ENOMEM; + } + + static struct dentry *efivarfs_mount(struct file_system_type *fs_type, +-- +1.7.12.1 + + +From d3b7165568bcb50e4526c3dadda59e43f6681bc0 Mon Sep 17 00:00:00 2001 +From: Jeremy Kerr <jeremy.kerr@canonical.com> +Date: Thu, 11 Oct 2012 21:19:11 +0800 +Subject: [PATCH 10/17] efivarfs: Implement exclusive access for + {get,set}_variable + +Currently, efivarfs does not enforce exclusion over the get_variable and +set_variable operations. Section 7.1 of UEFI requires us to only allow a +single processor to enter {get,set}_variable services at once. + +This change acquires the efivars->lock over calls to these operations +from the efivarfs paths. + +Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 68 +++++++++++++++++++++++++++++----------------- + 1 file changed, 43 insertions(+), 25 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 216086d..d478c56 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -690,35 +690,45 @@ static ssize_t efivarfs_file_write(struct file *file, + goto out; + } + ++ /* ++ * The lock here protects the get_variable call, the conditional ++ * set_variable call, and removal of the variable from the efivars ++ * list (in the case of an authenticated delete). ++ */ ++ spin_lock(&efivars->lock); ++ + status = efivars->ops->set_variable(var->var.VariableName, + &var->var.VendorGuid, + attributes, datasize, + data); + +- switch (status) { +- case EFI_SUCCESS: +- break; +- case EFI_INVALID_PARAMETER: +- count = -EINVAL; +- goto out; +- case EFI_OUT_OF_RESOURCES: +- count = -ENOSPC; +- goto out; +- case EFI_DEVICE_ERROR: +- count = -EIO; +- goto out; +- case EFI_WRITE_PROTECTED: +- count = -EROFS; +- goto out; +- case EFI_SECURITY_VIOLATION: +- count = -EACCES; +- goto out; +- case EFI_NOT_FOUND: +- count = -ENOENT; +- goto out; +- default: +- count = -EINVAL; +- goto out; ++ if (status != EFI_SUCCESS) { ++ spin_unlock(&efivars->lock); ++ kfree(data); ++ ++ switch (status) { ++ case EFI_INVALID_PARAMETER: ++ count = -EINVAL; ++ break; ++ case EFI_OUT_OF_RESOURCES: ++ count = -ENOSPC; ++ break; ++ case EFI_DEVICE_ERROR: ++ count = -EIO; ++ break; ++ case EFI_WRITE_PROTECTED: ++ count = -EROFS; ++ break; ++ case EFI_SECURITY_VIOLATION: ++ count = -EACCES; ++ break; ++ case EFI_NOT_FOUND: ++ count = -ENOENT; ++ break; ++ default: ++ count = -EINVAL; ++ } ++ return count; + } + + /* +@@ -734,12 +744,12 @@ static ssize_t efivarfs_file_write(struct file *file, + NULL); + + if (status == EFI_BUFFER_TOO_SMALL) { ++ spin_unlock(&efivars->lock); + mutex_lock(&inode->i_mutex); + i_size_write(inode, newdatasize + sizeof(attributes)); + mutex_unlock(&inode->i_mutex); + + } else if (status == EFI_NOT_FOUND) { +- spin_lock(&efivars->lock); + list_del(&var->list); + spin_unlock(&efivars->lock); + efivar_unregister(var); +@@ -747,6 +757,7 @@ static ssize_t efivarfs_file_write(struct file *file, + dput(file->f_dentry); + + } else { ++ spin_unlock(&efivars->lock); + pr_warn("efivarfs: inconsistent EFI variable implementation? " + "status = %lx\n", status); + } +@@ -768,9 +779,11 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + void *data; + ssize_t size = 0; + ++ spin_lock(&efivars->lock); + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, + &attributes, &datasize, NULL); ++ spin_unlock(&efivars->lock); + + if (status != EFI_BUFFER_TOO_SMALL) + return 0; +@@ -780,10 +793,13 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + if (!data) + return 0; + ++ spin_lock(&efivars->lock); + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, + &attributes, &datasize, + (data + 4)); ++ spin_unlock(&efivars->lock); ++ + if (status != EFI_SUCCESS) + goto out_free; + +@@ -1004,11 +1020,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + /* copied by the above to local storage in the dentry. */ + kfree(name); + ++ spin_lock(&efivars->lock); + efivars->ops->get_variable(entry->var.VariableName, + &entry->var.VendorGuid, + &entry->var.Attributes, + &size, + NULL); ++ spin_unlock(&efivars->lock); + + mutex_lock(&inode->i_mutex); + inode->i_private = entry; +-- +1.7.12.1 + + +From 90a462e9cf439a1987e0f9434d1f615addcc1970 Mon Sep 17 00:00:00 2001 +From: Jeremy Kerr <jeremy.kerr@canonical.com> +Date: Fri, 19 Oct 2012 15:16:45 +0800 +Subject: [PATCH 11/17] efi: Clarify GUID length calculations + +At present, the handling of GUIDs in efivar file names isn't consistent. +We use GUID_LEN in some places, and 38 in others (GUID_LEN plus +separator), and implicitly use the presence of the trailing NUL. + +This change removes the trailing NUL from GUID_LEN, so that we're +explicitly adding it when required. We also replace magic numbers +with GUID_LEN, and clarify the comments where appropriate. + +We also fix the allocation size in efivar_create_sysfs_entry, where +we're allocating one byte too much, due to counting the trailing NUL +twice - once when calculating short_name_size, and once in the kzalloc. + +Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 33 +++++++++++++++++++++++++-------- + 1 file changed, 25 insertions(+), 8 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index d478c56..a93e401 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -95,7 +95,12 @@ MODULE_LICENSE("GPL"); + MODULE_VERSION(EFIVARS_VERSION); + + #define DUMP_NAME_LEN 52 +-#define GUID_LEN 37 ++ ++/* ++ * Length of a GUID string (strlen("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee")) ++ * not including trailing NUL ++ */ ++#define GUID_LEN 36 + + /* + * The maximum size of VariableName + Data = 1024 +@@ -887,7 +892,11 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + struct efivar_entry *var; + int namelen, i = 0, err = 0; + +- if (dentry->d_name.len < 38) ++ /* ++ * We need a GUID, plus at least one letter for the variable name, ++ * plus the '-' separator ++ */ ++ if (dentry->d_name.len < GUID_LEN + 2) + return -EINVAL; + + inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); +@@ -900,7 +909,8 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + goto out; + } + +- namelen = dentry->d_name.len - GUID_LEN; ++ /* length of the variable name itself: remove GUID and separator */ ++ namelen = dentry->d_name.len - GUID_LEN - 1; + + efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1, + &var->var.VendorGuid); +@@ -994,8 +1004,8 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + + len = utf16_strlen(entry->var.VariableName); + +- /* GUID plus trailing NULL */ +- name = kmalloc(len + 38, GFP_ATOMIC); ++ /* name, plus '-', plus GUID, plus NUL*/ ++ name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC); + if (!name) + goto fail; + +@@ -1006,7 +1016,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + + efi_guid_unparse(&entry->var.VendorGuid, name + len + 1); + +- name[len+GUID_LEN] = '\0'; ++ name[len+GUID_LEN+1] = '\0'; + + inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, + S_IFREG | 0644, 0); +@@ -1435,11 +1445,18 @@ efivar_create_sysfs_entry(struct efivars *efivars, + efi_char16_t *variable_name, + efi_guid_t *vendor_guid) + { +- int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; ++ int i, short_name_size; + char *short_name; + struct efivar_entry *new_efivar; + +- short_name = kzalloc(short_name_size + 1, GFP_KERNEL); ++ /* ++ * Length of the variable bytes in ASCII, plus the '-' separator, ++ * plus the GUID, plus trailing NUL ++ */ ++ short_name_size = variable_name_size / sizeof(efi_char16_t) ++ + 1 + GUID_LEN + 1; ++ ++ short_name = kzalloc(short_name_size, GFP_KERNEL); + new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); + + if (!short_name || !new_efivar) { +-- +1.7.12.1 + + +From ecbf90823d85ebb41e68e6be01f476862d184825 Mon Sep 17 00:00:00 2001 +From: Matt Fleming <matt.fleming@intel.com> +Date: Tue, 16 Oct 2012 15:58:07 +0100 +Subject: [PATCH 12/17] efivarfs: Return an error if we fail to read a + variable + +Instead of always returning 0 in efivarfs_file_read(), even when we +fail to successfully read the variable, convert the EFI status to +something meaningful and return that to the caller. This way the user +will have some hint as to why the read failed. + +Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 62 +++++++++++++++++++++++++++------------------- + 1 file changed, 36 insertions(+), 26 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index a93e401..277e426 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -653,6 +653,36 @@ static int efivarfs_file_open(struct inode *inode, struct file *file) + return 0; + } + ++static int efi_status_to_err(efi_status_t status) ++{ ++ int err; ++ ++ switch (status) { ++ case EFI_INVALID_PARAMETER: ++ err = -EINVAL; ++ break; ++ case EFI_OUT_OF_RESOURCES: ++ err = -ENOSPC; ++ break; ++ case EFI_DEVICE_ERROR: ++ err = -EIO; ++ break; ++ case EFI_WRITE_PROTECTED: ++ err = -EROFS; ++ break; ++ case EFI_SECURITY_VIOLATION: ++ err = -EACCES; ++ break; ++ case EFI_NOT_FOUND: ++ err = -ENOENT; ++ break; ++ default: ++ err = -EINVAL; ++ } ++ ++ return err; ++} ++ + static ssize_t efivarfs_file_write(struct file *file, + const char __user *userbuf, size_t count, loff_t *ppos) + { +@@ -711,29 +741,7 @@ static ssize_t efivarfs_file_write(struct file *file, + spin_unlock(&efivars->lock); + kfree(data); + +- switch (status) { +- case EFI_INVALID_PARAMETER: +- count = -EINVAL; +- break; +- case EFI_OUT_OF_RESOURCES: +- count = -ENOSPC; +- break; +- case EFI_DEVICE_ERROR: +- count = -EIO; +- break; +- case EFI_WRITE_PROTECTED: +- count = -EROFS; +- break; +- case EFI_SECURITY_VIOLATION: +- count = -EACCES; +- break; +- case EFI_NOT_FOUND: +- count = -ENOENT; +- break; +- default: +- count = -EINVAL; +- } +- return count; ++ return efi_status_to_err(status); + } + + /* +@@ -791,12 +799,12 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + spin_unlock(&efivars->lock); + + if (status != EFI_BUFFER_TOO_SMALL) +- return 0; ++ return efi_status_to_err(status); + + data = kmalloc(datasize + 4, GFP_KERNEL); + + if (!data) +- return 0; ++ return -ENOMEM; + + spin_lock(&efivars->lock); + status = efivars->ops->get_variable(var->var.VariableName, +@@ -805,8 +813,10 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + (data + 4)); + spin_unlock(&efivars->lock); + +- if (status != EFI_SUCCESS) ++ if (status != EFI_SUCCESS) { ++ size = efi_status_to_err(status); + goto out_free; ++ } + + memcpy(data, &attributes, 4); + size = simple_read_from_buffer(userbuf, count, ppos, +-- +1.7.12.1 + + +From 39210330739b943856ff21b29b4a0804f4e8349f Mon Sep 17 00:00:00 2001 +From: Matt Fleming <matt.fleming@intel.com> +Date: Mon, 22 Oct 2012 15:23:29 +0100 +Subject: [PATCH 13/17] efivarfs: Replace magic number with sizeof(attributes) + +Seeing "+ 4" littered throughout the functions gets a bit +confusing. Use "sizeof(attributes)" which clearly explains what +quantity we're adding. + +Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 277e426..2c04434 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -801,7 +801,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + if (status != EFI_BUFFER_TOO_SMALL) + return efi_status_to_err(status); + +- data = kmalloc(datasize + 4, GFP_KERNEL); ++ data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL); + + if (!data) + return -ENOMEM; +@@ -810,7 +810,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, + &attributes, &datasize, +- (data + 4)); ++ (data + sizeof(attributes))); + spin_unlock(&efivars->lock); + + if (status != EFI_SUCCESS) { +@@ -818,9 +818,9 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + goto out_free; + } + +- memcpy(data, &attributes, 4); ++ memcpy(data, &attributes, sizeof(attributes)); + size = simple_read_from_buffer(userbuf, count, ppos, +- data, datasize + 4); ++ data, datasize + sizeof(attributes)); + out_free: + kfree(data); + +-- +1.7.12.1 + + +From 5555f0af6294b3675a95a06da23101150644936d Mon Sep 17 00:00:00 2001 +From: Matt Fleming <matt.fleming@intel.com> +Date: Mon, 22 Oct 2012 15:51:45 +0100 +Subject: [PATCH 14/17] efivarfs: Add unique magic number + +Using pstore's superblock magic number is no doubt going to cause +problems in the future. Give efivarfs its own magic number. + +Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 2 +- + include/uapi/linux/magic.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 2c04434..3b0cf9a 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -991,7 +991,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + sb->s_maxbytes = MAX_LFS_FILESIZE; + sb->s_blocksize = PAGE_CACHE_SIZE; + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; +- sb->s_magic = PSTOREFS_MAGIC; ++ sb->s_magic = EFIVARFS_MAGIC; + sb->s_op = &efivarfs_ops; + sb->s_time_gran = 1; + +diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h +index e15192c..12f68c7 100644 +--- a/include/uapi/linux/magic.h ++++ b/include/uapi/linux/magic.h +@@ -27,6 +27,7 @@ + #define ISOFS_SUPER_MAGIC 0x9660 + #define JFFS2_SUPER_MAGIC 0x72b6 + #define PSTOREFS_MAGIC 0x6165676C ++#define EFIVARFS_MAGIC 0xde5e81e4 + + #define MINIX_SUPER_MAGIC 0x137F /* minix v1 fs, 14 char names */ + #define MINIX_SUPER_MAGIC2 0x138F /* minix v1 fs, 30 char names */ +-- +1.7.12.1 + + +From a42845c67f2386b164d0c5d8220838d7faf5a409 Mon Sep 17 00:00:00 2001 +From: Matt Fleming <matt.fleming@intel.com> +Date: Tue, 23 Oct 2012 12:35:43 +0100 +Subject: [PATCH 15/17] efivarfs: Make 'datasize' unsigned long + +There's no reason to declare 'datasize' as an int, since the majority +of the functions it's passed to expect an unsigned long anyway. Plus, +this way we avoid any sign problems during arithmetic. + +Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 3b0cf9a..6a858d1 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -692,7 +692,7 @@ static ssize_t efivarfs_file_write(struct file *file, + void *data; + u32 attributes; + struct inode *inode = file->f_mapping->host; +- int datasize = count - sizeof(attributes); ++ unsigned long datasize = count - sizeof(attributes); + unsigned long newdatasize; + + if (count < sizeof(attributes)) +-- +1.7.12.1 + + +From a268bdf6d7ce623ea4bdfcf39aa52ed3fbfdfd65 Mon Sep 17 00:00:00 2001 +From: Matt Fleming <matt.fleming@intel.com> +Date: Tue, 23 Oct 2012 12:41:03 +0100 +Subject: [PATCH 16/17] efivarfs: Return a consistent error when + efivarfs_get_inode() fails + +Instead of returning -ENOSPC if efivarfs_get_inode() fails we should +be returning -ENOMEM, since running out of memory is the only reason +it can fail. Furthermore, that's the error value used everywhere else +in this file. It's also less likely to confuse users that hit this +error case. + +Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 6a858d1..58cec62 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -911,7 +911,7 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + + inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); + if (!inode) +- return -ENOSPC; ++ return -ENOMEM; + + var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); + if (!var) { +-- +1.7.12.1 + + +From 9c3136c987175b179c0aa725d76cda156894f918 Mon Sep 17 00:00:00 2001 +From: Matt Fleming <matt.fleming@intel.com> +Date: Fri, 26 Oct 2012 12:18:53 +0100 +Subject: [PATCH 17/17] efivarfs: Fix return value of efivarfs_file_write() + +We're stuffing a variable of type size_t (unsigned) into a ssize_t +(signed) which, even though both types should be the same number of +bits, it's just asking for sign issues to be introduced. + +Cc: Jeremy Kerr <jeremy.kerr@canonical.com> +Reported-by: Alan Cox <alan@lxorguk.ukuu.org.uk> +Signed-off-by: Matt Fleming <matt.fleming@intel.com> +--- + drivers/firmware/efivars.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 58cec62..9ac9340 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -694,6 +694,7 @@ static ssize_t efivarfs_file_write(struct file *file, + struct inode *inode = file->f_mapping->host; + unsigned long datasize = count - sizeof(attributes); + unsigned long newdatasize; ++ ssize_t bytes = 0; + + if (count < sizeof(attributes)) + return -EINVAL; +@@ -706,22 +707,22 @@ static ssize_t efivarfs_file_write(struct file *file, + efivars = var->efivars; + + if (copy_from_user(&attributes, userbuf, sizeof(attributes))) { +- count = -EFAULT; ++ bytes = -EFAULT; + goto out; + } + + if (attributes & ~(EFI_VARIABLE_MASK)) { +- count = -EINVAL; ++ bytes = -EINVAL; + goto out; + } + + if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) { +- count = -EFAULT; ++ bytes = -EFAULT; + goto out; + } + + if (validate_var(&var->var, data, datasize) == false) { +- count = -EINVAL; ++ bytes = -EINVAL; + goto out; + } + +@@ -744,6 +745,8 @@ static ssize_t efivarfs_file_write(struct file *file, + return efi_status_to_err(status); + } + ++ bytes = count; ++ + /* + * Writing to the variable may have caused a change in size (which + * could either be an append or an overwrite), or the variable to be +@@ -778,7 +781,7 @@ static ssize_t efivarfs_file_write(struct file *file, + out: + kfree(data); + +- return count; ++ return bytes; + } + + static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, +-- +1.7.12.1 + diff --git a/freed-ora/current/f18/exec-do-not-leave-bprm-interp-on-stack.patch b/freed-ora/current/f18/exec-do-not-leave-bprm-interp-on-stack.patch index 2a4b2dd28..5198824ed 100644 --- a/freed-ora/current/f18/exec-do-not-leave-bprm-interp-on-stack.patch +++ b/freed-ora/current/f18/exec-do-not-leave-bprm-interp-on-stack.patch @@ -1,6 +1,6 @@ -From 20ae2081584450e552735a3df968ce5b5946a607 Mon Sep 17 00:00:00 2001 +From 6752ab4cb863fc63ed85f1ca78a42235c09fad83 Mon Sep 17 00:00:00 2001 From: Kees Cook <keescook@chromium.org> -Date: Mon, 26 Nov 2012 08:56:37 -0500 +Date: Mon, 26 Nov 2012 09:07:50 -0500 Subject: [PATCH 1/2] exec: do not leave bprm->interp on stack If a series of scripts are executed, each triggering module loading via @@ -73,10 +73,10 @@ index d3b8c1f..df49d48 100644 /* * OK, now restart the process with the interpreter's dentry. diff --git a/fs/exec.c b/fs/exec.c -index fab2c6d..59896ae 100644 +index 0039055..c6e6de4 100644 --- a/fs/exec.c +++ b/fs/exec.c -@@ -1202,9 +1202,24 @@ void free_bprm(struct linux_binprm *bprm) +@@ -1175,9 +1175,24 @@ void free_bprm(struct linux_binprm *bprm) mutex_unlock(¤t->signal->cred_guard_mutex); abort_creds(bprm->cred); } @@ -102,10 +102,10 @@ index fab2c6d..59896ae 100644 * install the new credentials for this executable */ diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h -index 366422b..eb53e15 100644 +index cfcc6bf..de0628e 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h -@@ -128,6 +128,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm, +@@ -114,6 +114,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm, unsigned long stack_top, int executable_stack); extern int bprm_mm_init(struct linux_binprm *bprm); diff --git a/freed-ora/current/f18/exec-use-eloop-for-max-recursion-depth.patch b/freed-ora/current/f18/exec-use-eloop-for-max-recursion-depth.patch index cbaff2f7a..a3c48884f 100644 --- a/freed-ora/current/f18/exec-use-eloop-for-max-recursion-depth.patch +++ b/freed-ora/current/f18/exec-use-eloop-for-max-recursion-depth.patch @@ -1,4 +1,4 @@ -From 4ae8186cd77835b45f1b35edb4ce70309287bfc3 Mon Sep 17 00:00:00 2001 +From ba1b23d05259e31d30a78017cdfbc010dcb08aa6 Mon Sep 17 00:00:00 2001 From: Kees Cook <keescook@chromium.org> Date: Mon, 26 Nov 2012 09:02:11 -0500 Subject: [PATCH 2/2] exec: use -ELOOP for max recursion depth @@ -98,10 +98,10 @@ index df49d48..8ae4be1 100644 fput(bprm->file); bprm->file = NULL; diff --git a/fs/exec.c b/fs/exec.c -index 59896ae..541cc51 100644 +index c6e6de4..85c1f9e 100644 --- a/fs/exec.c +++ b/fs/exec.c -@@ -1398,6 +1398,10 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) +@@ -1371,6 +1371,10 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) struct linux_binfmt *fmt; pid_t old_pid, old_vpid; @@ -112,7 +112,7 @@ index 59896ae..541cc51 100644 retval = security_bprm_check(bprm); if (retval) return retval; -@@ -1422,12 +1426,8 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) +@@ -1395,12 +1399,8 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) if (!try_module_get(fmt->module)) continue; read_unlock(&binfmt_lock); @@ -127,10 +127,10 @@ index 59896ae..541cc51 100644 if (retval >= 0) { if (depth == 0) { diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h -index eb53e15..5bab59b 100644 +index de0628e..54135f6 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h -@@ -68,8 +68,6 @@ struct linux_binprm { +@@ -54,8 +54,6 @@ struct linux_binprm { #define BINPRM_FLAGS_EXECFD_BIT 1 #define BINPRM_FLAGS_EXECFD (1 << BINPRM_FLAGS_EXECFD_BIT) @@ -138,7 +138,7 @@ index eb53e15..5bab59b 100644 - /* Function parameter for binfmt->coredump */ struct coredump_params { - long signr; + siginfo_t *siginfo; -- 1.8.0 diff --git a/freed-ora/current/f18/fs-lock-splice_read-and-splice_write-functions.patch b/freed-ora/current/f18/fs-lock-splice_read-and-splice_write-functions.patch deleted file mode 100644 index 938cbd9f5..000000000 --- a/freed-ora/current/f18/fs-lock-splice_read-and-splice_write-functions.patch +++ /dev/null @@ -1,74 +0,0 @@ -Lock splice_read and splice_write functions - -commit 1a25b1c4ce189e3926f2981f3302352a930086db -Author: Mikulas Patocka <mpatocka@redhat.com> -Date: Mon Oct 15 17:20:17 2012 -0400 - - Lock splice_read and splice_write functions - - Functions generic_file_splice_read and generic_file_splice_write access - the pagecache directly. For block devices these functions must be locked - so that block size is not changed while they are in progress. - - This patch is an additional fix for commit b87570f5d349 ("Fix a crash - when block device is read and block size is changed at the same time") - that locked aio_read, aio_write and mmap against block size change. - - Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> - Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> - -Index: linux-3.6.x86_64/fs/block_dev.c -=================================================================== ---- linux-3.6.x86_64.orig/fs/block_dev.c 2012-11-16 17:12:57.352936580 -0500 -+++ linux-3.6.x86_64/fs/block_dev.c 2012-11-16 17:13:11.908887989 -0500 -@@ -1662,6 +1662,39 @@ - return ret; - } - -+static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags) -+{ -+ ssize_t ret; -+ struct block_device *bdev = I_BDEV(file->f_mapping->host); -+ -+ percpu_down_read(&bdev->bd_block_size_semaphore); -+ -+ ret = generic_file_splice_read(file, ppos, pipe, len, flags); -+ -+ percpu_up_read(&bdev->bd_block_size_semaphore); -+ -+ return ret; -+} -+ -+static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe, -+ struct file *file, loff_t *ppos, size_t len, -+ unsigned int flags) -+{ -+ ssize_t ret; -+ struct block_device *bdev = I_BDEV(file->f_mapping->host); -+ -+ percpu_down_read(&bdev->bd_block_size_semaphore); -+ -+ ret = generic_file_splice_write(pipe, file, ppos, len, flags); -+ -+ percpu_up_read(&bdev->bd_block_size_semaphore); -+ -+ return ret; -+} -+ -+ - /* - * Try to release a page associated with block device when the system - * is under memory pressure. -@@ -1700,8 +1733,8 @@ - #ifdef CONFIG_COMPAT - .compat_ioctl = compat_blkdev_ioctl, - #endif -- .splice_read = generic_file_splice_read, -- .splice_write = generic_file_splice_write, -+ .splice_read = blkdev_splice_read, -+ .splice_write = blkdev_splice_write, - }; - - int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) diff --git a/freed-ora/current/f18/handle-efi-roms.patch b/freed-ora/current/f18/handle-efi-roms.patch index 3002b1f89..bc080542b 100644 --- a/freed-ora/current/f18/handle-efi-roms.patch +++ b/freed-ora/current/f18/handle-efi-roms.patch @@ -131,62 +131,6 @@ diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c . /* * See if we have Graphics Output Protocol */ -@@ -276,8 +392,9 @@ - nr_gops = size / sizeof(void *); - for (i = 0; i < nr_gops; i++) { - struct efi_graphics_output_mode_info *info; -- efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; -- void *pciio; -+ efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; -+ bool conout_found = false; -+ void *dummy; - void *h = gop_handle[i]; - - status = efi_call_phys3(sys_table->boottime->handle_protocol, -@@ -285,19 +402,21 @@ - if (status != EFI_SUCCESS) - continue; - -- efi_call_phys3(sys_table->boottime->handle_protocol, -- h, &pciio_proto, &pciio); -+ status = efi_call_phys3(sys_table->boottime->handle_protocol, -+ h, &conout_proto, &dummy); -+ -+ if (status == EFI_SUCCESS) -+ conout_found = true; - - status = efi_call_phys4(gop->query_mode, gop, - gop->mode->mode, &size, &info); -- if (status == EFI_SUCCESS && (!first_gop || pciio)) { -+ if (status == EFI_SUCCESS && (!first_gop || conout_found)) { - /* -- * Apple provide GOPs that are not backed by -- * real hardware (they're used to handle -- * multiple displays). The workaround is to -- * search for a GOP implementing the PCIIO -- * protocol, and if one isn't found, to just -- * fallback to the first GOP. -+ * Systems that use the UEFI Console Splitter may -+ * provide multiple GOP devices, not all of which are -+ * backed by real hardware. The workaround is to search -+ * for a GOP implementing the ConOut protocol, and if -+ * one isn't found, to just fall back to the first GOP. - */ - width = info->horizontal_resolution; - height = info->vertical_resolution; -@@ -308,10 +427,10 @@ - pixels_per_scan_line = info->pixels_per_scan_line; - - /* -- * Once we've found a GOP supporting PCIIO, -+ * Once we've found a GOP supporting ConOut, - * don't bother looking any further. - */ -- if (pciio) -+ if (conout_found) - break; - - first_gop = gop; @@ -1052,6 +1171,8 @@ setup_graphics(boot_params); @@ -196,20 +140,6 @@ diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c . status = efi_call_phys3(sys_table->boottime->allocate_pool, EFI_LOADER_DATA, sizeof(*gdt), (void **)&gdt); -diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h ---- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h 2012-07-21 16:58:29.000000000 -0400 -+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h 2012-08-22 15:25:40.530244882 -0400 -@@ -14,6 +14,10 @@ - #define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) - #define EFI_READ_CHUNK_SIZE (1024 * 1024) - -+#define EFI_CONSOLE_OUT_DEVICE_GUID \ -+ EFI_GUID( 0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \ -+ 0x3f, 0xc1, 0x4d ) -+ - #define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 - #define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 - #define PIXEL_BIT_MASK 2 diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h --- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h 2012-08-22 15:26:32.485522068 -0400 +++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h 2012-08-22 15:25:40.530244882 -0400 @@ -332,25 +262,19 @@ diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c ../kernel-3.5.fc diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c --- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c 2012-07-21 16:58:29.000000000 -0400 +++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c 2012-08-22 15:25:40.531244893 -0400 -@@ -118,11 +118,17 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) - void __iomem *rom; - - /* +@@ -126,6 +126,12 @@ + /* primary video rom always starts here */ + start = (loff_t)0xC0000; + *size = 0x20000; /* cover C000:0 through E000:0 */ ++ /* + * Some devices may provide ROMs via a source other than the BAR + */ -+ if (pdev->rom && pdev->romlen) { ++ } else if (pdev->rom && pdev->romlen) { + *size = pdev->romlen; + return phys_to_virt(pdev->rom); -+ /* - * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy - * memory map if the VGA enable bit of the Bridge Control register is - * set for embedded VGA. - */ -- if (res->flags & IORESOURCE_ROM_SHADOW) { -+ } else if (res->flags & IORESOURCE_ROM_SHADOW) { - /* primary video rom always starts here */ - start = (loff_t)0xC0000; - *size = 0x20000; /* cover C000:0 through E000:0 */ + } else { + if (res->flags & + (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) { @@ -219,7 +225,8 @@ if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) return; diff --git a/freed-ora/current/f18/kernel.spec b/freed-ora/current/f18/kernel.spec index bd7df2941..3e0678fc8 100644 --- a/freed-ora/current/f18/kernel.spec +++ b/freed-ora/current/f18/kernel.spec @@ -62,13 +62,13 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 3.1-rc7-git1 starts with a 3.0 base, # which yields a base_sublevel of 0. -%define base_sublevel 6 +%define base_sublevel 7 # librev starts empty, then 1, etc, as the linux-libre tarball # changes. This is only used to determine which tarball to use. @@ -78,9 +78,9 @@ Summary: The Linux kernel %define basegnu -gnu%{?librev} # To be inserted between "patch" and "-2.6.". -%define stablelibre -3.6%{?stablegnux} -#define rcrevlibre -3.6%{?rcrevgnux} -#define gitrevlibre -3.6%{?gitrevgnux} +#define stablelibre -3.7%{?stablegnux} +#define rcrevlibre -3.7%{?rcrevgnux} +#define gitrevlibre -3.7%{?gitrevgnux} %if 0%{?stablelibre:1} %define stablegnu -gnu%{?librev} @@ -112,7 +112,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 11 +%define stable_update 1 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -468,6 +468,14 @@ Summary: The Linux kernel %endif %endif +# Should make listnewconfig fail if there's config options +# printed out? +%if %{nopatches}%{using_upstream_branch} +%define listnewconfig_fail 0 +%else +%define listnewconfig_fail 1 +%endif + # To temporarily exclude an architecture from being built, add it to # %%nobuildarches. Do _NOT_ use the ExclusiveArch: line, because if we # don't build kernel-headers then the new build system will no longer let @@ -582,7 +590,7 @@ ExclusiveOS: Linux BuildRequires: module-init-tools, patch >= 2.5.4, bash >= 2.03, sh-utils, tar BuildRequires: bzip2, xz, findutils, gzip, m4, perl, make >= 3.78, diffutils, gawk BuildRequires: gcc >= 3.4.2, binutils >= 2.12, redhat-rpm-config, hmaccalc -BuildRequires: net-tools +BuildRequires: net-tools, hostname BuildRequires: xmlto, asciidoc %if %{with_sparse} BuildRequires: sparse >= 0.4.1 @@ -720,10 +728,6 @@ Patch100: taint-vbox.patch Patch110: vmbugon-warnon.patch -Patch150: team-net-next-20120808.patch -Patch151: team-net-next-update-20120927.patch -Patch152: team-net-next-20121205.patch - Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch Patch394: linux-2.6-acpi-debug-infinite-loop.patch @@ -745,12 +749,11 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch # crypto/ -Patch900: modsign-upstream-3.7.patch Patch901: modsign-post-KS-jwb.patch # secure boot Patch1000: secure-boot-20121212.patch -Patch1001: efivarfs-3.6.patch +Patch1001: efivarfs-3.7.patch # Improve PCI support on UEFI Patch1100: handle-efi-roms.patch @@ -799,7 +802,6 @@ Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch # ARM Patch21000: arm-read_current_timer.patch Patch21001: arm-fix-omapdrm.patch -Patch21002: arm-fix_radio_shark.patch Patch21003: arm-alignment-faults.patch # OMAP @@ -809,7 +811,6 @@ Patch21005: arm-tegra-usb-no-reset-linux33.patch Patch21006: arm-tegra-sdhci-module-fix.patch # ARM highbank patches -Patch21010: arm-highbank-sata-fix.patch # ARM exynos4 Patch21020: arm-smdk310-regulator-fix.patch @@ -823,33 +824,9 @@ Patch22000: weird-root-dentry-name-debug.patch #selinux ptrace child permissions Patch22001: selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 869904 869909 CVE-2012-4508 -Patch22080: 0001-ext4-ext4_inode_info-diet.patch -Patch22081: 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch -Patch22082: 0003-ext4-fix-unwritten-counter-leakage.patch -Patch22083: 0004-ext4-completed_io-locking-cleanup.patch -Patch22084: 0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch -Patch22085: 0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch -Patch22086: 0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch -Patch22087: 0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch -Patch22088: 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch -Patch22089: 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch -Patch22090: 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch -Patch22091: 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch - -Patch22100: uprobes-upstream-backport.patch - #rhbz 871078 Patch22112: USB-report-submission-of-active-URBs.patch -#rhbz 869341 -Patch22113: smp_irq_move_cleanup_interrupt.patch - -#rhbz 812129 -Patch22120: block-fix-a-crash-when-block-device-is.patch -Patch22121: blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch -Patch22122: fs-lock-splice_read-and-splice_write-functions.patch - #rhbz 874791 Patch22125: Bluetooth-Add-support-for-BCM20702A0.patch @@ -860,9 +837,6 @@ Patch21226: vt-Drop-K_OFF-for-VC_MUTE.patch Patch21228: exec-do-not-leave-bprm-interp-on-stack.patch Patch21229: exec-use-eloop-for-max-recursion-depth.patch -#rhbz 869629 -Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch - #rhbz 851278 Patch21231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch @@ -1505,23 +1479,17 @@ ApplyPatch taint-vbox.patch ApplyPatch vmbugon-warnon.patch -ApplyPatch team-net-next-20120808.patch -ApplyPatch team-net-next-update-20120927.patch -ApplyPatch team-net-next-20121205.patch - # Architecture patches # x86(-64) # # ARM # -ApplyPatch arm-read_current_timer.patch -ApplyPatch arm-fix-omapdrm.patch -ApplyPatch arm-fix_radio_shark.patch +#ApplyPatch arm-read_current_timer.patch +#ApplyPatch arm-fix-omapdrm.patch ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch ApplyPatch arm-tegra-sdhci-module-fix.patch -ApplyPatch arm-highbank-sata-fix.patch ApplyPatch arm-alignment-faults.patch ApplyPatch arm-smdk310-regulator-fix.patch ApplyPatch arm-origen-regulator-fix.patch @@ -1592,11 +1560,10 @@ ApplyPatch linux-2.6-crash-driver.patch ApplyPatch linux-2.6-e1000-ich9-montevina.patch # crypto/ -ApplyPatch modsign-upstream-3.7.patch ApplyPatch modsign-post-KS-jwb.patch # secure boot -ApplyPatch efivarfs-3.6.patch +ApplyPatch efivarfs-3.7.patch ApplyPatch secure-boot-20121212.patch # Improved PCI support for UEFI @@ -1639,8 +1606,8 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch lis3-improve-handling-of-null-rate.patch -ApplyPatch 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch -ApplyPatch 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch +#ApplyPatch 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch +#ApplyPatch 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch #rhbz 754518 ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -1650,33 +1617,9 @@ ApplyPatch weird-root-dentry-name-debug.patch #selinux ptrace child permissions ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 869904 869909 CVE-2012-4508 -ApplyPatch 0001-ext4-ext4_inode_info-diet.patch -ApplyPatch 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch -ApplyPatch 0003-ext4-fix-unwritten-counter-leakage.patch -ApplyPatch 0004-ext4-completed_io-locking-cleanup.patch -ApplyPatch 0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch -ApplyPatch 0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch -ApplyPatch 0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch -ApplyPatch 0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch -ApplyPatch 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch -ApplyPatch 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch -ApplyPatch 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch -ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch - -ApplyPatch uprobes-upstream-backport.patch - #rhbz 871078 ApplyPatch USB-report-submission-of-active-URBs.patch -#rhbz 869341 -ApplyPatch smp_irq_move_cleanup_interrupt.patch - -#rhbz 812129 -ApplyPatch block-fix-a-crash-when-block-device-is.patch -ApplyPatch blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch -ApplyPatch fs-lock-splice_read-and-splice_write-functions.patch - #rhbz 874791 ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch @@ -1687,9 +1630,6 @@ ApplyPatch vt-Drop-K_OFF-for-VC_MUTE.patch ApplyPatch exec-do-not-leave-bprm-interp-on-stack.patch ApplyPatch exec-use-eloop-for-max-recursion-depth.patch -#rhbz 869629 -ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch - #rhbz 851278 ApplyPatch 8139cp-revert-set-ring-address-before-enabling-receiver.patch -R ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch @@ -1729,17 +1669,23 @@ done rm -f kernel-%{version}-*debug.config %endif -# run oldconfig over the config files (except when noarch) -if [ "%{_target_cpu}" != "noarch" ]; then - for i in kernel-*-%{_target_cpu}*.config - do - mv $i .config - Arch=`head -1 .config | cut -b 3-` - make ARCH=$Arch oldnoconfig - echo "# $Arch" > configs/$i - cat .config >> configs/$i - done -fi +# now run oldconfig over all the config files +for i in *.config +do + mv $i .config + Arch=`head -1 .config | cut -b 3-` + make ARCH=$Arch listnewconfig | grep -E '^CONFIG_' >.newoptions || true +%if %{listnewconfig_fail} + if [ -s .newoptions ]; then + cat .newoptions + exit 1 + fi +%endif + rm -f .newoptions + make ARCH=$Arch oldnoconfig + echo "# $Arch" > configs/$i + cat .config >> configs/$i +done # end of kernel config %endif @@ -2459,6 +2405,7 @@ fi %dir %{_libexecdir}/perf-core %{_libexecdir}/perf-core/* %{_mandir}/man[1-8]/perf* +%{_sysconfdir}/bash_completion.d/perf %doc linux-%{KVERREL}/tools/perf/Documentation/examples.txt %files -n python-perf-libre @@ -2578,6 +2525,20 @@ fi # ||----w | # || || %changelog +* Fri Jan 4 2013 Alexandre Oliva <lxoliva@fsfla.org> -libre +- GNU Linux-libre 3.7.1 + +* Thu Jan 03 2013 Josh Boyer <jwboyer@redhat.com> - 3.7.1-2 +- Fixup secure boot patchset for 3.7 rebase +- Package bash completion script for perf + +* Thu Jan 03 2013 Dave Jones <davej@redhat.com> +- Rebase to 3.7.1 + +* Wed Jan 02 2013 Josh Boyer <jwboyer@redhat.com> +- Fix autofs issue in 3.6 (rhbz 874372) +- BR the hostname package (rhbz 886113) + * Mon Dec 17 2012 Alexandre Oliva <lxoliva@fsfla.org> -libre - GNU Linux-libre 3.6.11-gnu @@ -2799,6 +2760,7 @@ fi - Linux 3.6.0 - Disable debugging options. +<<<<<<< HEAD * Fri Sep 28 2012 Josh Boyer <jwboyer@redhat.com> - 3.6.0-0.rc7.git3.1 - Linux v3.6-rc7-103-g6672d90 @@ -4866,6 +4828,8 @@ fi * Mon May 30 2011 Kyle McMartin <kyle@redhat.com> - Trimmed changelog, see fedpkg git for earlier history. +======= +>>>>>>> 1c6f1e3 ### # The following Emacs magic makes C-c C-e use UTC dates. # Local Variables: diff --git a/freed-ora/current/f18/linux-2.6-serial-460800.patch b/freed-ora/current/f18/linux-2.6-serial-460800.patch index 979b248d5..0e68378e7 100644 --- a/freed-ora/current/f18/linux-2.6-serial-460800.patch +++ b/freed-ora/current/f18/linux-2.6-serial-460800.patch @@ -28,14 +28,14 @@ index 2209620..659c1bb 100644 quot = uart_get_divisor(port, baud); @@ -2240,7 +2251,7 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, - struct uart_8250_port *up = (struct uart_8250_port *)port; + container_of(port, struct uart_8250_port, port); unsigned char cval, fcr = 0; unsigned long flags; - unsigned int baud, quot; + unsigned int baud, quot, max_baud; + int fifo_bug = 0; switch (termios->c_cflag & CSIZE) { - case CS5: @@ -2272,9 +2283,10 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, /* * Ask the core to calculate the divisor for us. diff --git a/freed-ora/current/f18/linux-libre-3.6-gnu.tar.xz.sign b/freed-ora/current/f18/linux-libre-3.6-gnu.tar.xz.sign deleted file mode 100644 index dbdf5e6d0..000000000 --- a/freed-ora/current/f18/linux-libre-3.6-gnu.tar.xz.sign +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2.0.18 (GNU/Linux) - -iEYEABECAAYFAlBo9TQACgkQvLfPh359R6c5GACgkzXtyZfBtqJqbVGOvIoSvtHh -RQEAn3ZxxgMk1RVT75ywYpP3gbz7QZjV -=VOuw ------END PGP SIGNATURE----- diff --git a/freed-ora/current/f18/linux-libre-3.6-gnu.xdelta.xz b/freed-ora/current/f18/linux-libre-3.6-gnu.xdelta.xz Binary files differdeleted file mode 100644 index 4f3f73070..000000000 --- a/freed-ora/current/f18/linux-libre-3.6-gnu.xdelta.xz +++ /dev/null diff --git a/freed-ora/current/f18/linux-libre-3.6-gnu.xdelta.xz.sign b/freed-ora/current/f18/linux-libre-3.6-gnu.xdelta.xz.sign deleted file mode 100644 index 295579272..000000000 --- a/freed-ora/current/f18/linux-libre-3.6-gnu.xdelta.xz.sign +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2.0.18 (GNU/Linux) - -iEYEABECAAYFAlBo9TUACgkQvLfPh359R6cCLACfcy8Pd21g94qq7+3hYtLaowT4 -J7wAoJDOcfwOJHwN8SkxfmkEonO8V0Bm -=A8ay ------END PGP SIGNATURE----- diff --git a/freed-ora/current/f18/linux-libre-3.7-gnu.tar.xz.sign b/freed-ora/current/f18/linux-libre-3.7-gnu.tar.xz.sign new file mode 100644 index 000000000..c49487a65 --- /dev/null +++ b/freed-ora/current/f18/linux-libre-3.7-gnu.tar.xz.sign @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.18 (GNU/Linux) + +iEYEABECAAYFAlDGubkACgkQvLfPh359R6dyvQCgn1oX7jcr2tiBiabLjHDwuHD/ +bfYAoKmSnj+Ks8sWyLmQVNRlEc/jtdY1 +=Fa9B +-----END PGP SIGNATURE----- diff --git a/freed-ora/current/f18/linux-libre-3.7-gnu.xdelta.xz b/freed-ora/current/f18/linux-libre-3.7-gnu.xdelta.xz Binary files differnew file mode 100644 index 000000000..f1929c01b --- /dev/null +++ b/freed-ora/current/f18/linux-libre-3.7-gnu.xdelta.xz diff --git a/freed-ora/current/f18/linux-libre-3.7-gnu.xdelta.xz.sign b/freed-ora/current/f18/linux-libre-3.7-gnu.xdelta.xz.sign new file mode 100644 index 000000000..123cb9ef3 --- /dev/null +++ b/freed-ora/current/f18/linux-libre-3.7-gnu.xdelta.xz.sign @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.18 (GNU/Linux) + +iEYEABECAAYFAlDGuboACgkQvLfPh359R6d/4ACePuNek3206kBQyeD1OBcLkNIy +kCIAnRlb9I2DMFdBXFh+/bj0CaX1NpPR +=ppPM +-----END PGP SIGNATURE----- diff --git a/freed-ora/current/f18/lis3-improve-handling-of-null-rate.patch b/freed-ora/current/f18/lis3-improve-handling-of-null-rate.patch index 98512564a..30ed26d80 100644 --- a/freed-ora/current/f18/lis3-improve-handling-of-null-rate.patch +++ b/freed-ora/current/f18/lis3-improve-handling-of-null-rate.patch @@ -28,9 +28,9 @@ index 35c67e0..42dce2a 100644 -static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000}; +/* LIS3DC: 0 = power off, above 9 = undefined */ +static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000, -1, -1, -1, -1, -1, -1}; + static int lis3_3dlh_rates[4] = {50, 100, 400, 1000}; /* ODR is Output Data Rate */ - static int lis3lv02d_get_odr(struct lis3lv02d *lis3) @@ -202,12 +203,11 @@ static int lis3lv02d_get_odr(struct lis3lv02d *lis3) return lis3->odrs[(ctrl >> shift)]; } diff --git a/freed-ora/current/f18/modsign-upstream-3.7.patch b/freed-ora/current/f18/modsign-upstream-3.7.patch deleted file mode 100644 index 33fd0592f..000000000 --- a/freed-ora/current/f18/modsign-upstream-3.7.patch +++ /dev/null @@ -1,10997 +0,0 @@ -From 9d501208ff48eb3ecc0d1ac8d897c38e99d18161 Mon Sep 17 00:00:00 2001 -From: Rusty Russell <rusty@rustcorp.com.au> -Date: Wed, 26 Sep 2012 10:09:40 +0100 -Subject: [PATCH 01/37] module: signature checking hook - -We do a very simple search for a particular string appended to the module -(which is cache-hot and about to be SHA'd anyway). There's both a config -option and a boot parameter which control whether we accept or fail with -unsigned modules and modules that are signed with an unknown key. - -If module signing is enabled, the kernel will be tainted if a module is -loaded that is unsigned or has a signature for which we don't have the -key. - -(Useful feedback and tweaks by David Howells <dhowells@redhat.com>) - -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - Documentation/kernel-parameters.txt | 6 +++ - include/linux/module.h | 8 ++++ - init/Kconfig | 14 ++++++ - kernel/Makefile | 1 + - kernel/module-internal.h | 13 ++++++ - kernel/module.c | 93 ++++++++++++++++++++++++++++++++++++- - kernel/module_signing.c | 23 +++++++++ - 7 files changed, 157 insertions(+), 1 deletion(-) - create mode 100644 kernel/module-internal.h - create mode 100644 kernel/module_signing.c - -diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index ad7e2e5..9b2b8d3 100644 ---- a/Documentation/kernel-parameters.txt -+++ b/Documentation/kernel-parameters.txt -@@ -1582,6 +1582,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. - log everything. Information is printed at KERN_DEBUG - so loglevel=8 may also need to be specified. - -+ module.sig_enforce -+ [KNL] When CONFIG_MODULE_SIG is set, this means that -+ modules without (valid) signatures will fail to load. -+ Note that if CONFIG_MODULE_SIG_ENFORCE is set, that -+ is always true, so this option does nothing. -+ - mousedev.tap_time= - [MOUSE] Maximum time between finger touching and - leaving touchpad surface for touch to be considered -diff --git a/include/linux/module.h b/include/linux/module.h -index fbcafe2..7760c6d 100644 ---- a/include/linux/module.h -+++ b/include/linux/module.h -@@ -21,6 +21,9 @@ - #include <linux/percpu.h> - #include <asm/module.h> - -+/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */ -+#define MODULE_SIG_STRING "~Module signature appended~\n" -+ - /* Not Yet Implemented */ - #define MODULE_SUPPORTED_DEVICE(name) - -@@ -260,6 +263,11 @@ struct module - const unsigned long *unused_gpl_crcs; - #endif - -+#ifdef CONFIG_MODULE_SIG -+ /* Signature was verified. */ -+ bool sig_ok; -+#endif -+ - /* symbols that will be GPL-only in the near future. */ - const struct kernel_symbol *gpl_future_syms; - const unsigned long *gpl_future_crcs; -diff --git a/init/Kconfig b/init/Kconfig -index af6c7f8..7452e19 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1585,6 +1585,20 @@ config MODULE_SRCVERSION_ALL - the version). With this option, such a "srcversion" field - will be created for all modules. If unsure, say N. - -+config MODULE_SIG -+ bool "Module signature verification" -+ depends on MODULES -+ help -+ Check modules for valid signatures upon load: the signature -+ is simply appended to the module. For more information see -+ Documentation/module-signing.txt. -+ -+config MODULE_SIG_FORCE -+ bool "Require modules to be validly signed" -+ depends on MODULE_SIG -+ help -+ Reject unsigned modules or signed modules for which we don't have a -+ key. Without this, such modules will simply taint the kernel. - endif # MODULES - - config INIT_ALL_POSSIBLE -diff --git a/kernel/Makefile b/kernel/Makefile -index c0cc67a..08ba8a6 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -55,6 +55,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o - obj-$(CONFIG_PROVE_LOCKING) += spinlock.o - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += module.o -+obj-$(CONFIG_MODULE_SIG) += module_signing.o - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -diff --git a/kernel/module-internal.h b/kernel/module-internal.h -new file mode 100644 -index 0000000..033c17f ---- /dev/null -+++ b/kernel/module-internal.h -@@ -0,0 +1,13 @@ -+/* Module internals -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+extern int mod_verify_sig(const void *mod, unsigned long modlen, -+ const void *sig, unsigned long siglen); -diff --git a/kernel/module.c b/kernel/module.c -index 9ad9ee9..7efb415 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -58,6 +58,7 @@ - #include <linux/jump_label.h> - #include <linux/pfn.h> - #include <linux/bsearch.h> -+#include "module-internal.h" - - #define CREATE_TRACE_POINTS - #include <trace/events/module.h> -@@ -102,6 +103,43 @@ static LIST_HEAD(modules); - struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ - #endif /* CONFIG_KGDB_KDB */ - -+#ifdef CONFIG_MODULE_SIG -+#ifdef CONFIG_MODULE_SIG_FORCE -+static bool sig_enforce = true; -+#else -+static bool sig_enforce = false; -+ -+static int param_set_bool_enable_only(const char *val, -+ const struct kernel_param *kp) -+{ -+ int err; -+ bool test; -+ struct kernel_param dummy_kp = *kp; -+ -+ dummy_kp.arg = &test; -+ -+ err = param_set_bool(val, &dummy_kp); -+ if (err) -+ return err; -+ -+ /* Don't let them unset it once it's set! */ -+ if (!test && sig_enforce) -+ return -EROFS; -+ -+ if (test) -+ sig_enforce = true; -+ return 0; -+} -+ -+static const struct kernel_param_ops param_ops_bool_enable_only = { -+ .set = param_set_bool_enable_only, -+ .get = param_get_bool, -+}; -+#define param_check_bool_enable_only param_check_bool -+ -+module_param(sig_enforce, bool_enable_only, 0644); -+#endif /* !CONFIG_MODULE_SIG_FORCE */ -+#endif /* CONFIG_MODULE_SIG */ - - /* Block module loading/unloading? */ - int modules_disabled = 0; -@@ -136,6 +174,7 @@ struct load_info { - unsigned long symoffs, stroffs; - struct _ddebug *debug; - unsigned int num_debug; -+ bool sig_ok; - struct { - unsigned int sym, str, mod, vers, info, pcpu; - } index; -@@ -2399,7 +2438,49 @@ static inline void kmemleak_load_module(const struct module *mod, - } - #endif - --/* Sets info->hdr and info->len. */ -+#ifdef CONFIG_MODULE_SIG -+static int module_sig_check(struct load_info *info, -+ const void *mod, unsigned long *len) -+{ -+ int err = -ENOKEY; -+ const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; -+ const void *p = mod, *end = mod + *len; -+ -+ /* Poor man's memmem. */ -+ while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { -+ if (p + markerlen > end) -+ break; -+ -+ if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { -+ const void *sig = p + markerlen; -+ /* Truncate module up to signature. */ -+ *len = p - mod; -+ err = mod_verify_sig(mod, *len, sig, end - sig); -+ break; -+ } -+ p++; -+ } -+ -+ if (!err) { -+ info->sig_ok = true; -+ return 0; -+ } -+ -+ /* Not having a signature is only an error if we're strict. */ -+ if (err == -ENOKEY && !sig_enforce) -+ err = 0; -+ -+ return err; -+} -+#else /* !CONFIG_MODULE_SIG */ -+static int module_sig_check(struct load_info *info, -+ void *mod, unsigned long *len) -+{ -+ return 0; -+} -+#endif /* !CONFIG_MODULE_SIG */ -+ -+/* Sets info->hdr, info->len and info->sig_ok. */ - static int copy_and_check(struct load_info *info, - const void __user *umod, unsigned long len, - const char __user *uargs) -@@ -2419,6 +2500,10 @@ static int copy_and_check(struct load_info *info, - goto free_hdr; - } - -+ err = module_sig_check(info, hdr, &len); -+ if (err) -+ goto free_hdr; -+ - /* Sanity checks against insmoding binaries or wrong arch, - weird elf version */ - if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0 -@@ -2890,6 +2975,12 @@ static struct module *load_module(void __user *umod, - goto free_copy; - } - -+#ifdef CONFIG_MODULE_SIG -+ mod->sig_ok = info.sig_ok; -+ if (!mod->sig_ok) -+ add_taint_module(mod, TAINT_FORCED_MODULE); -+#endif -+ - /* Now module is in final location, initialize linked lists, etc. */ - err = module_unload_init(mod); - if (err) -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -new file mode 100644 -index 0000000..499728a ---- /dev/null -+++ b/kernel/module_signing.c -@@ -0,0 +1,23 @@ -+/* Module signature checker -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/err.h> -+#include "module-internal.h" -+ -+/* -+ * Verify the signature on a module. -+ */ -+int mod_verify_sig(const void *mod, unsigned long modlen, -+ const void *sig, unsigned long siglen) -+{ -+ return -ENOKEY; -+} --- -1.7.12.1 - - -From 82400c211d81ea36338fb8266b5c41710101a013 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Thu, 13 Sep 2012 13:06:29 +0100 -Subject: [PATCH 02/37] KEYS: Add payload preparsing opportunity prior to key - instantiate or update - -Give the key type the opportunity to preparse the payload prior to the -instantiation and update routines being called. This is done with the -provision of two new key type operations: - - int (*preparse)(struct key_preparsed_payload *prep); - void (*free_preparse)(struct key_preparsed_payload *prep); - -If the first operation is present, then it is called before key creation (in -the add/update case) or before the key semaphore is taken (in the update and -instantiate cases). The second operation is called to clean up if the first -was called. - -preparse() is given the opportunity to fill in the following structure: - - struct key_preparsed_payload { - char *description; - void *type_data[2]; - void *payload; - const void *data; - size_t datalen; - size_t quotalen; - }; - -Before the preparser is called, the first three fields will have been cleared, -the payload pointer and size will be stored in data and datalen and the default -quota size from the key_type struct will be stored into quotalen. - -The preparser may parse the payload in any way it likes and may store data in -the type_data[] and payload fields for use by the instantiate() and update() -ops. - -The preparser may also propose a description for the key by attaching it as a -string to the description field. This can be used by passing a NULL or "" -description to the add_key() system call or the key_create_or_update() -function. This cannot work with request_key() as that required the description -to tell the upcall about the key to be created. - -This, for example permits keys that store PGP public keys to generate their own -name from the user ID and public key fingerprint in the key. - -The instantiate() and update() operations are then modified to look like this: - - int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); - int (*update)(struct key *key, struct key_preparsed_payload *prep); - -and the new payload data is passed in *prep, whether or not it was preparsed. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - Documentation/security/keys.txt | 50 +++++++++++++- - fs/cifs/cifs_spnego.c | 6 +- - fs/cifs/cifsacl.c | 8 +-- - include/keys/user-type.h | 6 +- - include/linux/key-type.h | 35 +++++++++- - net/ceph/crypto.c | 9 +-- - net/dns_resolver/dns_key.c | 6 +- - net/rxrpc/ar-key.c | 40 +++++------ - security/keys/encrypted-keys/encrypted.c | 16 +++-- - security/keys/key.c | 114 ++++++++++++++++++++++--------- - security/keys/keyctl.c | 18 +++-- - security/keys/keyring.c | 6 +- - security/keys/request_key_auth.c | 8 +-- - security/keys/trusted.c | 16 +++-- - security/keys/user_defined.c | 14 ++-- - 15 files changed, 250 insertions(+), 102 deletions(-) - -diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt -index aa0dbd7..7d9ca92 100644 ---- a/Documentation/security/keys.txt -+++ b/Documentation/security/keys.txt -@@ -412,6 +412,10 @@ The main syscalls are: - to the keyring. In this case, an error will be generated if the process - does not have permission to write to the keyring. - -+ If the key type supports it, if the description is NULL or an empty -+ string, the key type will try and generate a description from the content -+ of the payload. -+ - The payload is optional, and the pointer can be NULL if not required by - the type. The payload is plen in size, and plen can be zero for an empty - payload. -@@ -1114,12 +1118,53 @@ The structure has a number of fields, some of which are mandatory: - it should return 0. - - -- (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); -+ (*) int (*preparse)(struct key_preparsed_payload *prep); -+ -+ This optional method permits the key type to attempt to parse payload -+ before a key is created (add key) or the key semaphore is taken (update or -+ instantiate key). The structure pointed to by prep looks like: -+ -+ struct key_preparsed_payload { -+ char *description; -+ void *type_data[2]; -+ void *payload; -+ const void *data; -+ size_t datalen; -+ size_t quotalen; -+ }; -+ -+ Before calling the method, the caller will fill in data and datalen with -+ the payload blob parameters; quotalen will be filled in with the default -+ quota size from the key type and the rest will be cleared. -+ -+ If a description can be proposed from the payload contents, that should be -+ attached as a string to the description field. This will be used for the -+ key description if the caller of add_key() passes NULL or "". -+ -+ The method can attach anything it likes to type_data[] and payload. These -+ are merely passed along to the instantiate() or update() operations. -+ -+ The method should return 0 if success ful or a negative error code -+ otherwise. -+ -+ -+ (*) void (*free_preparse)(struct key_preparsed_payload *prep); -+ -+ This method is only required if the preparse() method is provided, -+ otherwise it is unused. It cleans up anything attached to the -+ description, type_data and payload fields of the key_preparsed_payload -+ struct as filled in by the preparse() method. -+ -+ -+ (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); - - This method is called to attach a payload to a key during construction. - The payload attached need not bear any relation to the data passed to this - function. - -+ The prep->data and prep->datalen fields will define the original payload -+ blob. If preparse() was supplied then other fields may be filled in also. -+ - If the amount of data attached to the key differs from the size in - keytype->def_datalen, then key_payload_reserve() should be called. - -@@ -1135,6 +1180,9 @@ The structure has a number of fields, some of which are mandatory: - If this type of key can be updated, then this method should be provided. - It is called to update a key's payload from the blob of data provided. - -+ The prep->data and prep->datalen fields will define the original payload -+ blob. If preparse() was supplied then other fields may be filled in also. -+ - key_payload_reserve() should be called if the data length might change - before any changes are actually made. Note that if this succeeds, the type - is committed to changing the key because it's already been altered, so all -diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c -index e622863..086f381 100644 ---- a/fs/cifs/cifs_spnego.c -+++ b/fs/cifs/cifs_spnego.c -@@ -31,18 +31,18 @@ - - /* create a new cifs key */ - static int --cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen) -+cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - char *payload; - int ret; - - ret = -ENOMEM; -- payload = kmalloc(datalen, GFP_KERNEL); -+ payload = kmalloc(prep->datalen, GFP_KERNEL); - if (!payload) - goto error; - - /* attach the data */ -- memcpy(payload, data, datalen); -+ memcpy(payload, prep->data, prep->datalen); - key->payload.data = payload; - ret = 0; - -diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c -index 05f4dc2..f3c60e2 100644 ---- a/fs/cifs/cifsacl.c -+++ b/fs/cifs/cifsacl.c -@@ -167,17 +167,17 @@ static struct shrinker cifs_shrinker = { - }; - - static int --cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) -+cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - char *payload; - -- payload = kmalloc(datalen, GFP_KERNEL); -+ payload = kmalloc(prep->datalen, GFP_KERNEL); - if (!payload) - return -ENOMEM; - -- memcpy(payload, data, datalen); -+ memcpy(payload, prep->data, prep->datalen); - key->payload.data = payload; -- key->datalen = datalen; -+ key->datalen = prep->datalen; - return 0; - } - -diff --git a/include/keys/user-type.h b/include/keys/user-type.h -index bc9ec1d..5e452c8 100644 ---- a/include/keys/user-type.h -+++ b/include/keys/user-type.h -@@ -35,8 +35,10 @@ struct user_key_payload { - extern struct key_type key_type_user; - extern struct key_type key_type_logon; - --extern int user_instantiate(struct key *key, const void *data, size_t datalen); --extern int user_update(struct key *key, const void *data, size_t datalen); -+struct key_preparsed_payload; -+ -+extern int user_instantiate(struct key *key, struct key_preparsed_payload *prep); -+extern int user_update(struct key *key, struct key_preparsed_payload *prep); - extern int user_match(const struct key *key, const void *criterion); - extern void user_revoke(struct key *key); - extern void user_destroy(struct key *key); -diff --git a/include/linux/key-type.h b/include/linux/key-type.h -index f0c651c..518a53a 100644 ---- a/include/linux/key-type.h -+++ b/include/linux/key-type.h -@@ -26,6 +26,27 @@ struct key_construction { - struct key *authkey;/* authorisation for key being constructed */ - }; - -+/* -+ * Pre-parsed payload, used by key add, update and instantiate. -+ * -+ * This struct will be cleared and data and datalen will be set with the data -+ * and length parameters from the caller and quotalen will be set from -+ * def_datalen from the key type. Then if the preparse() op is provided by the -+ * key type, that will be called. Then the struct will be passed to the -+ * instantiate() or the update() op. -+ * -+ * If the preparse() op is given, the free_preparse() op will be called to -+ * clear the contents. -+ */ -+struct key_preparsed_payload { -+ char *description; /* Proposed key description (or NULL) */ -+ void *type_data[2]; /* Private key-type data */ -+ void *payload; /* Proposed payload */ -+ const void *data; /* Raw data */ -+ size_t datalen; /* Raw datalen */ -+ size_t quotalen; /* Quota length for proposed payload */ -+}; -+ - typedef int (*request_key_actor_t)(struct key_construction *key, - const char *op, void *aux); - -@@ -45,18 +66,28 @@ struct key_type { - /* vet a description */ - int (*vet_description)(const char *description); - -+ /* Preparse the data blob from userspace that is to be the payload, -+ * generating a proposed description and payload that will be handed to -+ * the instantiate() and update() ops. -+ */ -+ int (*preparse)(struct key_preparsed_payload *prep); -+ -+ /* Free a preparse data structure. -+ */ -+ void (*free_preparse)(struct key_preparsed_payload *prep); -+ - /* instantiate a key of this type - * - this method should call key_payload_reserve() to determine if the - * user's quota will hold the payload - */ -- int (*instantiate)(struct key *key, const void *data, size_t datalen); -+ int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); - - /* update a key of this type (optional) - * - this method should call key_payload_reserve() to recalculate the - * quota consumption - * - the key must be locked against read when modifying - */ -- int (*update)(struct key *key, const void *data, size_t datalen); -+ int (*update)(struct key *key, struct key_preparsed_payload *prep); - - /* match a key against a description */ - int (*match)(const struct key *key, const void *desc); -diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c -index 9da7fdd..af14cb4 100644 ---- a/net/ceph/crypto.c -+++ b/net/ceph/crypto.c -@@ -423,14 +423,15 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, - } - } - --int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) -+int ceph_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - struct ceph_crypto_key *ckey; -+ size_t datalen = prep->datalen; - int ret; - void *p; - - ret = -EINVAL; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - goto err; - - ret = key_payload_reserve(key, datalen); -@@ -443,8 +444,8 @@ int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) - goto err; - - /* TODO ceph_crypto_key_decode should really take const input */ -- p = (void *)data; -- ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen); -+ p = (void *)prep->data; -+ ret = ceph_crypto_key_decode(ckey, &p, (char*)prep->data+datalen); - if (ret < 0) - goto err_ckey; - -diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c -index d9507dd..859ab8b 100644 ---- a/net/dns_resolver/dns_key.c -+++ b/net/dns_resolver/dns_key.c -@@ -59,13 +59,13 @@ const struct cred *dns_resolver_cache; - * "ip1,ip2,...#foo=bar" - */ - static int --dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen) -+dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - struct user_key_payload *upayload; - unsigned long derrno; - int ret; -- size_t result_len = 0; -- const char *data = _data, *end, *opt; -+ size_t datalen = prep->datalen, result_len = 0; -+ const char *data = prep->data, *end, *opt; - - kenter("%%%d,%s,'%*.*s',%zu", - key->serial, key->description, -diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c -index 8b1f9f4..106c5a6 100644 ---- a/net/rxrpc/ar-key.c -+++ b/net/rxrpc/ar-key.c -@@ -26,8 +26,8 @@ - #include "ar-internal.h" - - static int rxrpc_vet_description_s(const char *); --static int rxrpc_instantiate(struct key *, const void *, size_t); --static int rxrpc_instantiate_s(struct key *, const void *, size_t); -+static int rxrpc_instantiate(struct key *, struct key_preparsed_payload *); -+static int rxrpc_instantiate_s(struct key *, struct key_preparsed_payload *); - static void rxrpc_destroy(struct key *); - static void rxrpc_destroy_s(struct key *); - static void rxrpc_describe(const struct key *, struct seq_file *); -@@ -678,7 +678,7 @@ error: - * - * if no data is provided, then a no-security key is made - */ --static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) -+static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - const struct rxrpc_key_data_v1 *v1; - struct rxrpc_key_token *token, **pp; -@@ -686,26 +686,26 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) - u32 kver; - int ret; - -- _enter("{%x},,%zu", key_serial(key), datalen); -+ _enter("{%x},,%zu", key_serial(key), prep->datalen); - - /* handle a no-security key */ -- if (!data && datalen == 0) -+ if (!prep->data && prep->datalen == 0) - return 0; - - /* determine if the XDR payload format is being used */ -- if (datalen > 7 * 4) { -- ret = rxrpc_instantiate_xdr(key, data, datalen); -+ if (prep->datalen > 7 * 4) { -+ ret = rxrpc_instantiate_xdr(key, prep->data, prep->datalen); - if (ret != -EPROTO) - return ret; - } - - /* get the key interface version number */ - ret = -EINVAL; -- if (datalen <= 4 || !data) -+ if (prep->datalen <= 4 || !prep->data) - goto error; -- memcpy(&kver, data, sizeof(kver)); -- data += sizeof(kver); -- datalen -= sizeof(kver); -+ memcpy(&kver, prep->data, sizeof(kver)); -+ prep->data += sizeof(kver); -+ prep->datalen -= sizeof(kver); - - _debug("KEY I/F VERSION: %u", kver); - -@@ -715,11 +715,11 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) - - /* deal with a version 1 key */ - ret = -EINVAL; -- if (datalen < sizeof(*v1)) -+ if (prep->datalen < sizeof(*v1)) - goto error; - -- v1 = data; -- if (datalen != sizeof(*v1) + v1->ticket_length) -+ v1 = prep->data; -+ if (prep->datalen != sizeof(*v1) + v1->ticket_length) - goto error; - - _debug("SCIX: %u", v1->security_index); -@@ -784,17 +784,17 @@ error: - * instantiate a server secret key - * data should be a pointer to the 8-byte secret key - */ --static int rxrpc_instantiate_s(struct key *key, const void *data, -- size_t datalen) -+static int rxrpc_instantiate_s(struct key *key, -+ struct key_preparsed_payload *prep) - { - struct crypto_blkcipher *ci; - -- _enter("{%x},,%zu", key_serial(key), datalen); -+ _enter("{%x},,%zu", key_serial(key), prep->datalen); - -- if (datalen != 8) -+ if (prep->datalen != 8) - return -EINVAL; - -- memcpy(&key->type_data, data, 8); -+ memcpy(&key->type_data, prep->data, 8); - - ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(ci)) { -@@ -802,7 +802,7 @@ static int rxrpc_instantiate_s(struct key *key, const void *data, - return PTR_ERR(ci); - } - -- if (crypto_blkcipher_setkey(ci, data, 8) < 0) -+ if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) - BUG(); - - key->payload.data = ci; -diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c -index 2d1bb8a..9e1e005 100644 ---- a/security/keys/encrypted-keys/encrypted.c -+++ b/security/keys/encrypted-keys/encrypted.c -@@ -773,8 +773,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload, - * - * On success, return 0. Otherwise return errno. - */ --static int encrypted_instantiate(struct key *key, const void *data, -- size_t datalen) -+static int encrypted_instantiate(struct key *key, -+ struct key_preparsed_payload *prep) - { - struct encrypted_key_payload *epayload = NULL; - char *datablob = NULL; -@@ -782,16 +782,17 @@ static int encrypted_instantiate(struct key *key, const void *data, - char *master_desc = NULL; - char *decrypted_datalen = NULL; - char *hex_encoded_iv = NULL; -+ size_t datalen = prep->datalen; - int ret; - -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - datablob = kmalloc(datalen + 1, GFP_KERNEL); - if (!datablob) - return -ENOMEM; - datablob[datalen] = 0; -- memcpy(datablob, data, datalen); -+ memcpy(datablob, prep->data, datalen); - ret = datablob_parse(datablob, &format, &master_desc, - &decrypted_datalen, &hex_encoded_iv); - if (ret < 0) -@@ -834,16 +835,17 @@ static void encrypted_rcu_free(struct rcu_head *rcu) - * - * On success, return 0. Otherwise return errno. - */ --static int encrypted_update(struct key *key, const void *data, size_t datalen) -+static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) - { - struct encrypted_key_payload *epayload = key->payload.data; - struct encrypted_key_payload *new_epayload; - char *buf; - char *new_master_desc = NULL; - const char *format = NULL; -+ size_t datalen = prep->datalen; - int ret = 0; - -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - buf = kmalloc(datalen + 1, GFP_KERNEL); -@@ -851,7 +853,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) - return -ENOMEM; - - buf[datalen] = 0; -- memcpy(buf, data, datalen); -+ memcpy(buf, prep->data, datalen); - ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); - if (ret < 0) - goto out; -diff --git a/security/keys/key.c b/security/keys/key.c -index 50d96d4..1d039af 100644 ---- a/security/keys/key.c -+++ b/security/keys/key.c -@@ -412,8 +412,7 @@ EXPORT_SYMBOL(key_payload_reserve); - * key_construction_mutex. - */ - static int __key_instantiate_and_link(struct key *key, -- const void *data, -- size_t datalen, -+ struct key_preparsed_payload *prep, - struct key *keyring, - struct key *authkey, - unsigned long *_prealloc) -@@ -431,7 +430,7 @@ static int __key_instantiate_and_link(struct key *key, - /* can't instantiate twice */ - if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { - /* instantiate the key */ -- ret = key->type->instantiate(key, data, datalen); -+ ret = key->type->instantiate(key, prep); - - if (ret == 0) { - /* mark the key as being instantiated */ -@@ -482,22 +481,37 @@ int key_instantiate_and_link(struct key *key, - struct key *keyring, - struct key *authkey) - { -+ struct key_preparsed_payload prep; - unsigned long prealloc; - int ret; - -+ memset(&prep, 0, sizeof(prep)); -+ prep.data = data; -+ prep.datalen = datalen; -+ prep.quotalen = key->type->def_datalen; -+ if (key->type->preparse) { -+ ret = key->type->preparse(&prep); -+ if (ret < 0) -+ goto error; -+ } -+ - if (keyring) { - ret = __key_link_begin(keyring, key->type, key->description, - &prealloc); - if (ret < 0) -- return ret; -+ goto error_free_preparse; - } - -- ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, -+ ret = __key_instantiate_and_link(key, &prep, keyring, authkey, - &prealloc); - - if (keyring) - __key_link_end(keyring, key->type, prealloc); - -+error_free_preparse: -+ if (key->type->preparse) -+ key->type->free_preparse(&prep); -+error: - return ret; - } - -@@ -706,7 +720,7 @@ void key_type_put(struct key_type *ktype) - * if we get an error. - */ - static inline key_ref_t __key_update(key_ref_t key_ref, -- const void *payload, size_t plen) -+ struct key_preparsed_payload *prep) - { - struct key *key = key_ref_to_ptr(key_ref); - int ret; -@@ -722,7 +736,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref, - - down_write(&key->sem); - -- ret = key->type->update(key, payload, plen); -+ ret = key->type->update(key, prep); - if (ret == 0) - /* updating a negative key instantiates it */ - clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -@@ -774,6 +788,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - unsigned long flags) - { - unsigned long prealloc; -+ struct key_preparsed_payload prep; - const struct cred *cred = current_cred(); - struct key_type *ktype; - struct key *keyring, *key = NULL; -@@ -789,8 +804,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - } - - key_ref = ERR_PTR(-EINVAL); -- if (!ktype->match || !ktype->instantiate) -- goto error_2; -+ if (!ktype->match || !ktype->instantiate || -+ (!description && !ktype->preparse)) -+ goto error_put_type; - - keyring = key_ref_to_ptr(keyring_ref); - -@@ -798,18 +814,37 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - - key_ref = ERR_PTR(-ENOTDIR); - if (keyring->type != &key_type_keyring) -- goto error_2; -+ goto error_put_type; -+ -+ memset(&prep, 0, sizeof(prep)); -+ prep.data = payload; -+ prep.datalen = plen; -+ prep.quotalen = ktype->def_datalen; -+ if (ktype->preparse) { -+ ret = ktype->preparse(&prep); -+ if (ret < 0) { -+ key_ref = ERR_PTR(ret); -+ goto error_put_type; -+ } -+ if (!description) -+ description = prep.description; -+ key_ref = ERR_PTR(-EINVAL); -+ if (!description) -+ goto error_free_prep; -+ } - - ret = __key_link_begin(keyring, ktype, description, &prealloc); -- if (ret < 0) -- goto error_2; -+ if (ret < 0) { -+ key_ref = ERR_PTR(ret); -+ goto error_free_prep; -+ } - - /* if we're going to allocate a new key, we're going to have - * to modify the keyring */ - ret = key_permission(keyring_ref, KEY_WRITE); - if (ret < 0) { - key_ref = ERR_PTR(ret); -- goto error_3; -+ goto error_link_end; - } - - /* if it's possible to update this type of key, search for an existing -@@ -840,25 +875,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - perm, flags); - if (IS_ERR(key)) { - key_ref = ERR_CAST(key); -- goto error_3; -+ goto error_link_end; - } - - /* instantiate it and link it into the target keyring */ -- ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, -- &prealloc); -+ ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc); - if (ret < 0) { - key_put(key); - key_ref = ERR_PTR(ret); -- goto error_3; -+ goto error_link_end; - } - - key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); - -- error_3: -+error_link_end: - __key_link_end(keyring, ktype, prealloc); -- error_2: -+error_free_prep: -+ if (ktype->preparse) -+ ktype->free_preparse(&prep); -+error_put_type: - key_type_put(ktype); -- error: -+error: - return key_ref; - - found_matching_key: -@@ -866,10 +903,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - * - we can drop the locks first as we have the key pinned - */ - __key_link_end(keyring, ktype, prealloc); -- key_type_put(ktype); - -- key_ref = __key_update(key_ref, payload, plen); -- goto error; -+ key_ref = __key_update(key_ref, &prep); -+ goto error_free_prep; - } - EXPORT_SYMBOL(key_create_or_update); - -@@ -888,6 +924,7 @@ EXPORT_SYMBOL(key_create_or_update); - */ - int key_update(key_ref_t key_ref, const void *payload, size_t plen) - { -+ struct key_preparsed_payload prep; - struct key *key = key_ref_to_ptr(key_ref); - int ret; - -@@ -900,18 +937,31 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) - - /* attempt to update it if supported */ - ret = -EOPNOTSUPP; -- if (key->type->update) { -- down_write(&key->sem); -- -- ret = key->type->update(key, payload, plen); -- if (ret == 0) -- /* updating a negative key instantiates it */ -- clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -+ if (!key->type->update) -+ goto error; - -- up_write(&key->sem); -+ memset(&prep, 0, sizeof(prep)); -+ prep.data = payload; -+ prep.datalen = plen; -+ prep.quotalen = key->type->def_datalen; -+ if (key->type->preparse) { -+ ret = key->type->preparse(&prep); -+ if (ret < 0) -+ goto error; - } - -- error: -+ down_write(&key->sem); -+ -+ ret = key->type->update(key, &prep); -+ if (ret == 0) -+ /* updating a negative key instantiates it */ -+ clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -+ -+ up_write(&key->sem); -+ -+ if (key->type->preparse) -+ key->type->free_preparse(&prep); -+error: - return ret; - } - EXPORT_SYMBOL(key_update); -diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c -index 3364fbf..505d40b 100644 ---- a/security/keys/keyctl.c -+++ b/security/keys/keyctl.c -@@ -46,6 +46,9 @@ static int key_get_type_from_user(char *type, - * Extract the description of a new key from userspace and either add it as a - * new key to the specified keyring or update a matching key in that keyring. - * -+ * If the description is NULL or an empty string, the key type is asked to -+ * generate one from the payload. -+ * - * The keyring must be writable so that we can attach the key to it. - * - * If successful, the new key's serial number is returned, otherwise an error -@@ -72,10 +75,17 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, - if (ret < 0) - goto error; - -- description = strndup_user(_description, PAGE_SIZE); -- if (IS_ERR(description)) { -- ret = PTR_ERR(description); -- goto error; -+ description = NULL; -+ if (_description) { -+ description = strndup_user(_description, PAGE_SIZE); -+ if (IS_ERR(description)) { -+ ret = PTR_ERR(description); -+ goto error; -+ } -+ if (!*description) { -+ kfree(description); -+ description = NULL; -+ } - } - - /* pull the payload in if one was supplied */ -diff --git a/security/keys/keyring.c b/security/keys/keyring.c -index 81e7852..f04d8cf 100644 ---- a/security/keys/keyring.c -+++ b/security/keys/keyring.c -@@ -66,7 +66,7 @@ static inline unsigned keyring_hash(const char *desc) - * operations. - */ - static int keyring_instantiate(struct key *keyring, -- const void *data, size_t datalen); -+ struct key_preparsed_payload *prep); - static int keyring_match(const struct key *keyring, const void *criterion); - static void keyring_revoke(struct key *keyring); - static void keyring_destroy(struct key *keyring); -@@ -121,12 +121,12 @@ static void keyring_publish_name(struct key *keyring) - * Returns 0 on success, -EINVAL if given any data. - */ - static int keyring_instantiate(struct key *keyring, -- const void *data, size_t datalen) -+ struct key_preparsed_payload *prep) - { - int ret; - - ret = -EINVAL; -- if (datalen == 0) { -+ if (prep->datalen == 0) { - /* make the keyring available by name if it has one */ - keyring_publish_name(keyring); - ret = 0; -diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c -index 60d4e3f..85730d5 100644 ---- a/security/keys/request_key_auth.c -+++ b/security/keys/request_key_auth.c -@@ -19,7 +19,8 @@ - #include <asm/uaccess.h> - #include "internal.h" - --static int request_key_auth_instantiate(struct key *, const void *, size_t); -+static int request_key_auth_instantiate(struct key *, -+ struct key_preparsed_payload *); - static void request_key_auth_describe(const struct key *, struct seq_file *); - static void request_key_auth_revoke(struct key *); - static void request_key_auth_destroy(struct key *); -@@ -42,10 +43,9 @@ struct key_type key_type_request_key_auth = { - * Instantiate a request-key authorisation key. - */ - static int request_key_auth_instantiate(struct key *key, -- const void *data, -- size_t datalen) -+ struct key_preparsed_payload *prep) - { -- key->payload.data = (struct request_key_auth *) data; -+ key->payload.data = (struct request_key_auth *)prep->data; - return 0; - } - -diff --git a/security/keys/trusted.c b/security/keys/trusted.c -index 2d5d041..42036c7 100644 ---- a/security/keys/trusted.c -+++ b/security/keys/trusted.c -@@ -927,22 +927,23 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) - * - * On success, return 0. Otherwise return errno. - */ --static int trusted_instantiate(struct key *key, const void *data, -- size_t datalen) -+static int trusted_instantiate(struct key *key, -+ struct key_preparsed_payload *prep) - { - struct trusted_key_payload *payload = NULL; - struct trusted_key_options *options = NULL; -+ size_t datalen = prep->datalen; - char *datablob; - int ret = 0; - int key_cmd; - -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - datablob = kmalloc(datalen + 1, GFP_KERNEL); - if (!datablob) - return -ENOMEM; -- memcpy(datablob, data, datalen); -+ memcpy(datablob, prep->data, datalen); - datablob[datalen] = '\0'; - - options = trusted_options_alloc(); -@@ -1011,17 +1012,18 @@ static void trusted_rcu_free(struct rcu_head *rcu) - /* - * trusted_update - reseal an existing key with new PCR values - */ --static int trusted_update(struct key *key, const void *data, size_t datalen) -+static int trusted_update(struct key *key, struct key_preparsed_payload *prep) - { - struct trusted_key_payload *p = key->payload.data; - struct trusted_key_payload *new_p; - struct trusted_key_options *new_o; -+ size_t datalen = prep->datalen; - char *datablob; - int ret = 0; - - if (!p->migratable) - return -EPERM; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - datablob = kmalloc(datalen + 1, GFP_KERNEL); -@@ -1038,7 +1040,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) - goto out; - } - -- memcpy(datablob, data, datalen); -+ memcpy(datablob, prep->data, datalen); - datablob[datalen] = '\0'; - ret = datablob_parse(datablob, new_p, new_o); - if (ret != Opt_update) { -diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c -index c7660a2..55dc889 100644 ---- a/security/keys/user_defined.c -+++ b/security/keys/user_defined.c -@@ -58,13 +58,14 @@ EXPORT_SYMBOL_GPL(key_type_logon); - /* - * instantiate a user defined key - */ --int user_instantiate(struct key *key, const void *data, size_t datalen) -+int user_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - struct user_key_payload *upayload; -+ size_t datalen = prep->datalen; - int ret; - - ret = -EINVAL; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - goto error; - - ret = key_payload_reserve(key, datalen); -@@ -78,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) - - /* attach the data */ - upayload->datalen = datalen; -- memcpy(upayload->data, data, datalen); -+ memcpy(upayload->data, prep->data, datalen); - rcu_assign_keypointer(key, upayload); - ret = 0; - -@@ -92,13 +93,14 @@ EXPORT_SYMBOL_GPL(user_instantiate); - * update a user defined key - * - the key's semaphore is write-locked - */ --int user_update(struct key *key, const void *data, size_t datalen) -+int user_update(struct key *key, struct key_preparsed_payload *prep) - { - struct user_key_payload *upayload, *zap; -+ size_t datalen = prep->datalen; - int ret; - - ret = -EINVAL; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - goto error; - - /* construct a replacement payload */ -@@ -108,7 +110,7 @@ int user_update(struct key *key, const void *data, size_t datalen) - goto error; - - upayload->datalen = datalen; -- memcpy(upayload->data, data, datalen); -+ memcpy(upayload->data, prep->data, datalen); - - /* check the quota and attach the new data */ - zap = upayload; --- -1.7.12.1 - - -From 162ce9c1b0f28d36598975f8931f216245b7e778 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Thu, 13 Sep 2012 13:09:33 +0100 -Subject: [PATCH 03/37] MPILIB: Provide count_leading/trailing_zeros() based - on arch functions - -Provide count_leading/trailing_zeros() macros based on extant arch bit scanning -functions rather than reimplementing from scratch in MPILIB. - -Whilst we're at it, turn count_foo_zeros(n, x) into n = count_foo_zeros(x). - -Also move the definition to asm-generic as other people may be interested in -using it. - -Signed-off-by: David Howells <dhowells@redhat.com> -Cc: David S. Miller <davem@davemloft.net> -Cc: Dmitry Kasatkin <dmitry.kasatkin@intel.com> -Cc: Arnd Bergmann <arnd@arndb.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - include/asm-generic/bitops/count_zeros.h | 57 +++++++++++++ - lib/mpi/longlong.h | 138 +------------------------------ - lib/mpi/mpi-bit.c | 2 +- - lib/mpi/mpi-pow.c | 4 +- - 4 files changed, 62 insertions(+), 139 deletions(-) - create mode 100644 include/asm-generic/bitops/count_zeros.h - -diff --git a/include/asm-generic/bitops/count_zeros.h b/include/asm-generic/bitops/count_zeros.h -new file mode 100644 -index 0000000..97520d2 ---- /dev/null -+++ b/include/asm-generic/bitops/count_zeros.h -@@ -0,0 +1,57 @@ -+/* Count leading and trailing zeros functions -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#ifndef _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ -+#define _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ -+ -+#include <asm/bitops.h> -+ -+/** -+ * count_leading_zeros - Count the number of zeros from the MSB back -+ * @x: The value -+ * -+ * Count the number of leading zeros from the MSB going towards the LSB in @x. -+ * -+ * If the MSB of @x is set, the result is 0. -+ * If only the LSB of @x is set, then the result is BITS_PER_LONG-1. -+ * If @x is 0 then the result is COUNT_LEADING_ZEROS_0. -+ */ -+static inline int count_leading_zeros(unsigned long x) -+{ -+ if (sizeof(x) == 4) -+ return BITS_PER_LONG - fls(x); -+ else -+ return BITS_PER_LONG - fls64(x); -+} -+ -+#define COUNT_LEADING_ZEROS_0 BITS_PER_LONG -+ -+/** -+ * count_trailing_zeros - Count the number of zeros from the LSB forwards -+ * @x: The value -+ * -+ * Count the number of trailing zeros from the LSB going towards the MSB in @x. -+ * -+ * If the LSB of @x is set, the result is 0. -+ * If only the MSB of @x is set, then the result is BITS_PER_LONG-1. -+ * If @x is 0 then the result is COUNT_TRAILING_ZEROS_0. -+ */ -+static inline int count_trailing_zeros(unsigned long x) -+{ -+#define COUNT_TRAILING_ZEROS_0 (-1) -+ -+ if (sizeof(x) == 4) -+ return ffs(x); -+ else -+ return (x != 0) ? __ffs(x) : COUNT_TRAILING_ZEROS_0; -+} -+ -+#endif /* _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ */ -diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h -index 29f9862..678ce4f 100644 ---- a/lib/mpi/longlong.h -+++ b/lib/mpi/longlong.h -@@ -19,6 +19,8 @@ - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. */ - -+#include <asm-generic/bitops/count_zeros.h> -+ - /* You have to define the following before including this file: - * - * UWtype -- An unsigned type, default type for operations (typically a "word") -@@ -146,12 +148,6 @@ do { \ - : "1" ((USItype)(n1)), \ - "r" ((USItype)(n0)), \ - "r" ((USItype)(d))) -- --#define count_leading_zeros(count, x) \ -- __asm__ ("clz %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x))) --#define COUNT_LEADING_ZEROS_0 32 - #endif /* __a29k__ */ - - #if defined(__alpha) && W_TYPE_SIZE == 64 -@@ -298,11 +294,6 @@ extern UDItype __udiv_qrnnd(); - : "1" ((USItype)(nh)), \ - "0" ((USItype)(nl)), \ - "g" ((USItype)(d))) --#define count_leading_zeros(count, x) \ -- __asm__ ("bsch/1 %1,%0" \ -- : "=g" (count) \ -- : "g" ((USItype)(x)), \ -- "0" ((USItype)0)) - #endif - - /*************************************** -@@ -354,27 +345,6 @@ do { USItype __r; \ - } while (0) - extern USItype __udiv_qrnnd(); - #endif /* LONGLONG_STANDALONE */ --#define count_leading_zeros(count, x) \ --do { \ -- USItype __tmp; \ -- __asm__ ( \ -- "ldi 1,%0\n" \ -- "extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ -- "extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ -- "ldo 16(%0),%0 ; Yes. Perform add.\n" \ -- "extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ -- "extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ -- "ldo 8(%0),%0 ; Yes. Perform add.\n" \ -- "extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ -- "extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ -- "ldo 4(%0),%0 ; Yes. Perform add.\n" \ -- "extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ -- "extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ -- "ldo 2(%0),%0 ; Yes. Perform add.\n" \ -- "extru %1,30,1,%1 ; Extract bit 1.\n" \ -- "sub %0,%1,%0 ; Subtract it. " \ -- : "=r" (count), "=r" (__tmp) : "1" (x)); \ --} while (0) - #endif /* hppa */ - - /*************************************** -@@ -457,15 +427,6 @@ do { \ - : "0" ((USItype)(n0)), \ - "1" ((USItype)(n1)), \ - "rm" ((USItype)(d))) --#define count_leading_zeros(count, x) \ --do { \ -- USItype __cbtmp; \ -- __asm__ ("bsrl %1,%0" \ -- : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ -- (count) = __cbtmp ^ 31; \ --} while (0) --#define count_trailing_zeros(count, x) \ -- __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) - #ifndef UMUL_TIME - #define UMUL_TIME 40 - #endif -@@ -536,15 +497,6 @@ do { \ - "dI" ((USItype)(d))); \ - (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ - } while (0) --#define count_leading_zeros(count, x) \ --do { \ -- USItype __cbtmp; \ -- __asm__ ("scanbit %1,%0" \ -- : "=r" (__cbtmp) \ -- : "r" ((USItype)(x))); \ -- (count) = __cbtmp ^ 31; \ --} while (0) --#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ - #if defined(__i960mx) /* what is the proper symbol to test??? */ - #define rshift_rhlc(r, h, l, c) \ - do { \ -@@ -603,11 +555,6 @@ do { \ - : "0" ((USItype)(n0)), \ - "1" ((USItype)(n1)), \ - "dmi" ((USItype)(d))) --#define count_leading_zeros(count, x) \ -- __asm__ ("bfffo %1{%b2:%b2},%0" \ -- : "=d" ((USItype)(count)) \ -- : "od" ((USItype)(x)), "n" (0)) --#define COUNT_LEADING_ZEROS_0 32 - #else /* not mc68020 */ - #define umul_ppmm(xh, xl, a, b) \ - do { USItype __umul_tmp1, __umul_tmp2; \ -@@ -664,15 +611,6 @@ do { USItype __umul_tmp1, __umul_tmp2; \ - "rJ" ((USItype)(bh)), \ - "rJ" ((USItype)(al)), \ - "rJ" ((USItype)(bl))) --#define count_leading_zeros(count, x) \ --do { \ -- USItype __cbtmp; \ -- __asm__ ("ff1 %0,%1" \ -- : "=r" (__cbtmp) \ -- : "r" ((USItype)(x))); \ -- (count) = __cbtmp ^ 31; \ --} while (0) --#define COUNT_LEADING_ZEROS_0 63 /* sic */ - #if defined(__m88110__) - #define umul_ppmm(wh, wl, u, v) \ - do { \ -@@ -779,12 +717,6 @@ do { \ - : "0" (__xx.__ll), \ - "g" ((USItype)(d))); \ - (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) --#define count_trailing_zeros(count, x) \ --do { \ -- __asm__("ffsd %2,%0" \ -- : "=r"((USItype) (count)) \ -- : "0"((USItype) 0), "r"((USItype) (x))); \ -- } while (0) - #endif /* __ns32000__ */ - - /*************************************** -@@ -855,11 +787,6 @@ do { \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ - } while (0) --#define count_leading_zeros(count, x) \ -- __asm__ ("{cntlz|cntlzw} %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x))) --#define COUNT_LEADING_ZEROS_0 32 - #if defined(_ARCH_PPC) - #define umul_ppmm(ph, pl, m0, m1) \ - do { \ -@@ -1001,19 +928,6 @@ do { \ - } while (0) - #define UMUL_TIME 20 - #define UDIV_TIME 200 --#define count_leading_zeros(count, x) \ --do { \ -- if ((x) >= 0x10000) \ -- __asm__ ("clz %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x) >> 16)); \ -- else { \ -- __asm__ ("clz %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x))); \ -- (count) += 16; \ -- } \ --} while (0) - #endif /* RT/ROMP */ - - /*************************************** -@@ -1142,13 +1056,6 @@ do { \ - "rI" ((USItype)(d)) \ - : "%g1" __AND_CLOBBER_CC) - #define UDIV_TIME 37 --#define count_leading_zeros(count, x) \ -- __asm__ ("scan %1,0,%0" \ -- : "=r" ((USItype)(x)) \ -- : "r" ((USItype)(count))) --/* Early sparclites return 63 for an argument of 0, but they warn that future -- implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 -- undefined. */ - #endif /* __sparclite__ */ - #endif /* __sparc_v8__ */ - /* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ -@@ -1454,47 +1361,6 @@ do { \ - #define udiv_qrnnd __udiv_qrnnd_c - #endif - --#undef count_leading_zeros --#if !defined(count_leading_zeros) -- extern --#ifdef __STDC__ -- const --#endif -- unsigned char __clz_tab[]; --#define count_leading_zeros(count, x) \ --do { \ -- UWtype __xr = (x); \ -- UWtype __a; \ -- \ -- if (W_TYPE_SIZE <= 32) { \ -- __a = __xr < ((UWtype) 1 << 2*__BITS4) \ -- ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ -- : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ -- } \ -- else { \ -- for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ -- if (((__xr >> __a) & 0xff) != 0) \ -- break; \ -- } \ -- \ -- (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ --} while (0) -- /* This version gives a well-defined value for zero. */ --#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE --#endif -- --#if !defined(count_trailing_zeros) --/* Define count_trailing_zeros using count_leading_zeros. The latter might be -- defined in asm, but if it is not, the C version above is good enough. */ --#define count_trailing_zeros(count, x) \ --do { \ -- UWtype __ctz_x = (x); \ -- UWtype __ctz_c; \ -- count_leading_zeros(__ctz_c, __ctz_x & -__ctz_x); \ -- (count) = W_TYPE_SIZE - 1 - __ctz_c; \ --} while (0) --#endif -- - #ifndef UDIV_NEEDS_NORMALIZATION - #define UDIV_NEEDS_NORMALIZATION 0 - #endif -diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c -index 5687248..503537e 100644 ---- a/lib/mpi/mpi-bit.c -+++ b/lib/mpi/mpi-bit.c -@@ -45,7 +45,7 @@ unsigned mpi_get_nbits(MPI a) - if (a->nlimbs) { - mpi_limb_t alimb = a->d[a->nlimbs - 1]; - if (alimb) -- count_leading_zeros(n, alimb); -+ n = count_leading_zeros(alimb); - else - n = BITS_PER_MPI_LIMB; - n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB; -diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c -index 67f3e79..5464c87 100644 ---- a/lib/mpi/mpi-pow.c -+++ b/lib/mpi/mpi-pow.c -@@ -77,7 +77,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) - mp = mp_marker = mpi_alloc_limb_space(msize); - if (!mp) - goto enomem; -- count_leading_zeros(mod_shift_cnt, mod->d[msize - 1]); -+ mod_shift_cnt = count_leading_zeros(mod->d[msize - 1]); - if (mod_shift_cnt) - mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt); - else -@@ -169,7 +169,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) - - i = esize - 1; - e = ep[i]; -- count_leading_zeros(c, e); -+ c = count_leading_zeros(e); - e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ - c = BITS_PER_MPI_LIMB - 1 - c; - --- -1.7.12.1 - - -From ef184bcab1e58dafae2f02ae30824365bec1d27a Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Thu, 13 Sep 2012 15:17:21 +0100 -Subject: [PATCH 04/37] KEYS: Document asymmetric key type - -In-source documentation for the asymmetric key type. This will be located in: - - Documentation/crypto/asymmetric-keys.txt - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - Documentation/crypto/asymmetric-keys.txt | 312 +++++++++++++++++++++++++++++++ - 1 file changed, 312 insertions(+) - create mode 100644 Documentation/crypto/asymmetric-keys.txt - -diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt -new file mode 100644 -index 0000000..b767590 ---- /dev/null -+++ b/Documentation/crypto/asymmetric-keys.txt -@@ -0,0 +1,312 @@ -+ ============================================= -+ ASYMMETRIC / PUBLIC-KEY CRYPTOGRAPHY KEY TYPE -+ ============================================= -+ -+Contents: -+ -+ - Overview. -+ - Key identification. -+ - Accessing asymmetric keys. -+ - Signature verification. -+ - Asymmetric key subtypes. -+ - Instantiation data parsers. -+ -+ -+======== -+OVERVIEW -+======== -+ -+The "asymmetric" key type is designed to be a container for the keys used in -+public-key cryptography, without imposing any particular restrictions on the -+form or mechanism of the cryptography or form of the key. -+ -+The asymmetric key is given a subtype that defines what sort of data is -+associated with the key and provides operations to describe and destroy it. -+However, no requirement is made that the key data actually be stored in the -+key. -+ -+A completely in-kernel key retention and operation subtype can be defined, but -+it would also be possible to provide access to cryptographic hardware (such as -+a TPM) that might be used to both retain the relevant key and perform -+operations using that key. In such a case, the asymmetric key would then -+merely be an interface to the TPM driver. -+ -+Also provided is the concept of a data parser. Data parsers are responsible -+for extracting information from the blobs of data passed to the instantiation -+function. The first data parser that recognises the blob gets to set the -+subtype of the key and define the operations that can be done on that key. -+ -+A data parser may interpret the data blob as containing the bits representing a -+key, or it may interpret it as a reference to a key held somewhere else in the -+system (for example, a TPM). -+ -+ -+================== -+KEY IDENTIFICATION -+================== -+ -+If a key is added with an empty name, the instantiation data parsers are given -+the opportunity to pre-parse a key and to determine the description the key -+should be given from the content of the key. -+ -+This can then be used to refer to the key, either by complete match or by -+partial match. The key type may also use other criteria to refer to a key. -+ -+The asymmetric key type's match function can then perform a wider range of -+comparisons than just the straightforward comparison of the description with -+the criterion string: -+ -+ (1) If the criterion string is of the form "id:<hexdigits>" then the match -+ function will examine a key's fingerprint to see if the hex digits given -+ after the "id:" match the tail. For instance: -+ -+ keyctl search @s asymmetric id:5acc2142 -+ -+ will match a key with fingerprint: -+ -+ 1A00 2040 7601 7889 DE11 882C 3823 04AD 5ACC 2142 -+ -+ (2) If the criterion string is of the form "<subtype>:<hexdigits>" then the -+ match will match the ID as in (1), but with the added restriction that -+ only keys of the specified subtype (e.g. tpm) will be matched. For -+ instance: -+ -+ keyctl search @s asymmetric tpm:5acc2142 -+ -+Looking in /proc/keys, the last 8 hex digits of the key fingerprint are -+displayed, along with the subtype: -+ -+ 1a39e171 I----- 1 perm 3f010000 0 0 asymmetri modsign.0: DSA 5acc2142 [] -+ -+ -+========================= -+ACCESSING ASYMMETRIC KEYS -+========================= -+ -+For general access to asymmetric keys from within the kernel, the following -+inclusion is required: -+ -+ #include <crypto/public_key.h> -+ -+This gives access to functions for dealing with asymmetric / public keys. -+Three enums are defined there for representing public-key cryptography -+algorithms: -+ -+ enum pkey_algo -+ -+digest algorithms used by those: -+ -+ enum pkey_hash_algo -+ -+and key identifier representations: -+ -+ enum pkey_id_type -+ -+Note that the key type representation types are required because key -+identifiers from different standards aren't necessarily compatible. For -+instance, PGP generates key identifiers by hashing the key data plus some -+PGP-specific metadata, whereas X.509 has arbitrary certificate identifiers. -+ -+The operations defined upon a key are: -+ -+ (1) Signature verification. -+ -+Other operations are possible (such as encryption) with the same key data -+required for verification, but not currently supported, and others -+(eg. decryption and signature generation) require extra key data. -+ -+ -+SIGNATURE VERIFICATION -+---------------------- -+ -+An operation is provided to perform cryptographic signature verification, using -+an asymmetric key to provide or to provide access to the public key. -+ -+ int verify_signature(const struct key *key, -+ const struct public_key_signature *sig); -+ -+The caller must have already obtained the key from some source and can then use -+it to check the signature. The caller must have parsed the signature and -+transferred the relevant bits to the structure pointed to by sig. -+ -+ struct public_key_signature { -+ u8 *digest; -+ u8 digest_size; -+ enum pkey_hash_algo pkey_hash_algo : 8; -+ u8 nr_mpi; -+ union { -+ MPI mpi[2]; -+ ... -+ }; -+ }; -+ -+The algorithm used must be noted in sig->pkey_hash_algo, and all the MPIs that -+make up the actual signature must be stored in sig->mpi[] and the count of MPIs -+placed in sig->nr_mpi. -+ -+In addition, the data must have been digested by the caller and the resulting -+hash must be pointed to by sig->digest and the size of the hash be placed in -+sig->digest_size. -+ -+The function will return 0 upon success or -EKEYREJECTED if the signature -+doesn't match. -+ -+The function may also return -ENOTSUPP if an unsupported public-key algorithm -+or public-key/hash algorithm combination is specified or the key doesn't -+support the operation; -EBADMSG or -ERANGE if some of the parameters have weird -+data; or -ENOMEM if an allocation can't be performed. -EINVAL can be returned -+if the key argument is the wrong type or is incompletely set up. -+ -+ -+======================= -+ASYMMETRIC KEY SUBTYPES -+======================= -+ -+Asymmetric keys have a subtype that defines the set of operations that can be -+performed on that key and that determines what data is attached as the key -+payload. The payload format is entirely at the whim of the subtype. -+ -+The subtype is selected by the key data parser and the parser must initialise -+the data required for it. The asymmetric key retains a reference on the -+subtype module. -+ -+The subtype definition structure can be found in: -+ -+ #include <keys/asymmetric-subtype.h> -+ -+and looks like the following: -+ -+ struct asymmetric_key_subtype { -+ struct module *owner; -+ const char *name; -+ -+ void (*describe)(const struct key *key, struct seq_file *m); -+ void (*destroy)(void *payload); -+ int (*verify_signature)(const struct key *key, -+ const struct public_key_signature *sig); -+ }; -+ -+Asymmetric keys point to this with their type_data[0] member. -+ -+The owner and name fields should be set to the owning module and the name of -+the subtype. Currently, the name is only used for print statements. -+ -+There are a number of operations defined by the subtype: -+ -+ (1) describe(). -+ -+ Mandatory. This allows the subtype to display something in /proc/keys -+ against the key. For instance the name of the public key algorithm type -+ could be displayed. The key type will display the tail of the key -+ identity string after this. -+ -+ (2) destroy(). -+ -+ Mandatory. This should free the memory associated with the key. The -+ asymmetric key will look after freeing the fingerprint and releasing the -+ reference on the subtype module. -+ -+ (3) verify_signature(). -+ -+ Optional. These are the entry points for the key usage operations. -+ Currently there is only the one defined. If not set, the caller will be -+ given -ENOTSUPP. The subtype may do anything it likes to implement an -+ operation, including offloading to hardware. -+ -+ -+========================== -+INSTANTIATION DATA PARSERS -+========================== -+ -+The asymmetric key type doesn't generally want to store or to deal with a raw -+blob of data that holds the key data. It would have to parse it and error -+check it each time it wanted to use it. Further, the contents of the blob may -+have various checks that can be performed on it (eg. self-signatures, validity -+dates) and may contain useful data about the key (identifiers, capabilities). -+ -+Also, the blob may represent a pointer to some hardware containing the key -+rather than the key itself. -+ -+Examples of blob formats for which parsers could be implemented include: -+ -+ - OpenPGP packet stream [RFC 4880]. -+ - X.509 ASN.1 stream. -+ - Pointer to TPM key. -+ - Pointer to UEFI key. -+ -+During key instantiation each parser in the list is tried until one doesn't -+return -EBADMSG. -+ -+The parser definition structure can be found in: -+ -+ #include <keys/asymmetric-parser.h> -+ -+and looks like the following: -+ -+ struct asymmetric_key_parser { -+ struct module *owner; -+ const char *name; -+ -+ int (*parse)(struct key_preparsed_payload *prep); -+ }; -+ -+The owner and name fields should be set to the owning module and the name of -+the parser. -+ -+There is currently only a single operation defined by the parser, and it is -+mandatory: -+ -+ (1) parse(). -+ -+ This is called to preparse the key from the key creation and update paths. -+ In particular, it is called during the key creation _before_ a key is -+ allocated, and as such, is permitted to provide the key's description in -+ the case that the caller declines to do so. -+ -+ The caller passes a pointer to the following struct with all of the fields -+ cleared, except for data, datalen and quotalen [see -+ Documentation/security/keys.txt]. -+ -+ struct key_preparsed_payload { -+ char *description; -+ void *type_data[2]; -+ void *payload; -+ const void *data; -+ size_t datalen; -+ size_t quotalen; -+ }; -+ -+ The instantiation data is in a blob pointed to by data and is datalen in -+ size. The parse() function is not permitted to change these two values at -+ all, and shouldn't change any of the other values _unless_ they are -+ recognise the blob format and will not return -EBADMSG to indicate it is -+ not theirs. -+ -+ If the parser is happy with the blob, it should propose a description for -+ the key and attach it to ->description, ->type_data[0] should be set to -+ point to the subtype to be used, ->payload should be set to point to the -+ initialised data for that subtype, ->type_data[1] should point to a hex -+ fingerprint and quotalen should be updated to indicate how much quota this -+ key should account for. -+ -+ When clearing up, the data attached to ->type_data[1] and ->description -+ will be kfree()'d and the data attached to ->payload will be passed to the -+ subtype's ->destroy() method to be disposed of. A module reference for -+ the subtype pointed to by ->type_data[0] will be put. -+ -+ -+ If the data format is not recognised, -EBADMSG should be returned. If it -+ is recognised, but the key cannot for some reason be set up, some other -+ negative error code should be returned. On success, 0 should be returned. -+ -+ The key's fingerprint string may be partially matched upon. For a -+ public-key algorithm such as RSA and DSA this will likely be a printable -+ hex version of the key's fingerprint. -+ -+Functions are provided to register and unregister parsers: -+ -+ int register_asymmetric_key_parser(struct asymmetric_key_parser *parser); -+ void unregister_asymmetric_key_parser(struct asymmetric_key_parser *subtype); -+ -+Parsers may not have the same name. The names are otherwise only used for -+displaying in debugging messages. --- -1.7.12.1 - - -From 0e450d75d1067b6f45f1f6b58a530a5d95144373 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Thu, 13 Sep 2012 15:17:21 +0100 -Subject: [PATCH 05/37] KEYS: Implement asymmetric key type - -Create a key type that can be used to represent an asymmetric key type for use -in appropriate cryptographic operations, such as encryption, decryption, -signature generation and signature verification. - -The key type is "asymmetric" and can provide access to a variety of -cryptographic algorithms. - -Possibly, this would be better as "public_key" - but that has the disadvantage -that "public key" is an overloaded term. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - crypto/Kconfig | 1 + - crypto/Makefile | 1 + - crypto/asymmetric_keys/Kconfig | 13 +++ - crypto/asymmetric_keys/Makefile | 7 ++ - crypto/asymmetric_keys/asymmetric_keys.h | 15 +++ - crypto/asymmetric_keys/asymmetric_type.c | 156 +++++++++++++++++++++++++++++++ - include/keys/asymmetric-subtype.h | 55 +++++++++++ - include/keys/asymmetric-type.h | 25 +++++ - 8 files changed, 273 insertions(+) - create mode 100644 crypto/asymmetric_keys/Kconfig - create mode 100644 crypto/asymmetric_keys/Makefile - create mode 100644 crypto/asymmetric_keys/asymmetric_keys.h - create mode 100644 crypto/asymmetric_keys/asymmetric_type.c - create mode 100644 include/keys/asymmetric-subtype.h - create mode 100644 include/keys/asymmetric-type.h - -diff --git a/crypto/Kconfig b/crypto/Kconfig -index a323805..1ca0b24 100644 ---- a/crypto/Kconfig -+++ b/crypto/Kconfig -@@ -1043,5 +1043,6 @@ config CRYPTO_USER_API_SKCIPHER - key cipher algorithms. - - source "drivers/crypto/Kconfig" -+source crypto/asymmetric_keys/Kconfig - - endif # if CRYPTO -diff --git a/crypto/Makefile b/crypto/Makefile -index 30f33d6..ced472e 100644 ---- a/crypto/Makefile -+++ b/crypto/Makefile -@@ -96,3 +96,4 @@ obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o - # - obj-$(CONFIG_XOR_BLOCKS) += xor.o - obj-$(CONFIG_ASYNC_CORE) += async_tx/ -+obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/ -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -new file mode 100644 -index 0000000..cad29b3 ---- /dev/null -+++ b/crypto/asymmetric_keys/Kconfig -@@ -0,0 +1,13 @@ -+menuconfig ASYMMETRIC_KEY_TYPE -+ tristate "Asymmetric (public-key cryptographic) key type" -+ depends on KEYS -+ help -+ This option provides support for a key type that holds the data for -+ the asymmetric keys used for public key cryptographic operations such -+ as encryption, decryption, signature generation and signature -+ verification. -+ -+if ASYMMETRIC_KEY_TYPE -+ -+ -+endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -new file mode 100644 -index 0000000..b725bcc ---- /dev/null -+++ b/crypto/asymmetric_keys/Makefile -@@ -0,0 +1,7 @@ -+# -+# Makefile for asymmetric cryptographic keys -+# -+ -+obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o -+ -+asymmetric_keys-y := asymmetric_type.o -diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h -new file mode 100644 -index 0000000..515b634 ---- /dev/null -+++ b/crypto/asymmetric_keys/asymmetric_keys.h -@@ -0,0 +1,15 @@ -+/* Internal definitions for asymmetric key type -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+static inline const char *asymmetric_key_id(const struct key *key) -+{ -+ return key->type_data.p[1]; -+} -diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c -new file mode 100644 -index 0000000..bfb0424 ---- /dev/null -+++ b/crypto/asymmetric_keys/asymmetric_type.c -@@ -0,0 +1,156 @@ -+/* Asymmetric public-key cryptography key type -+ * -+ * See Documentation/security/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 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. -+ */ -+#include <keys/asymmetric-subtype.h> -+#include <linux/seq_file.h> -+#include <linux/module.h> -+#include <linux/slab.h> -+#include "asymmetric_keys.h" -+ -+MODULE_LICENSE("GPL"); -+ -+/* -+ * Match asymmetric keys on (part of) their name -+ * We have some shorthand methods for matching keys. We allow: -+ * -+ * "<desc>" - request a key by description -+ * "id:<id>" - request a key matching the ID -+ * "<subtype>:<id>" - request a key of a subtype -+ */ -+static int asymmetric_key_match(const struct key *key, const void *description) -+{ -+ const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); -+ const char *spec = description; -+ const char *id, *kid; -+ ptrdiff_t speclen; -+ size_t idlen, kidlen; -+ -+ if (!subtype || !spec || !*spec) -+ return 0; -+ -+ /* See if the full key description matches as is */ -+ if (key->description && strcmp(key->description, description) == 0) -+ return 1; -+ -+ /* All tests from here on break the criterion description into a -+ * specifier, a colon and then an identifier. -+ */ -+ id = strchr(spec, ':'); -+ if (!id) -+ return 0; -+ -+ speclen = id - spec; -+ id++; -+ -+ /* Anything after here requires a partial match on the ID string */ -+ kid = asymmetric_key_id(key); -+ if (!kid) -+ return 0; -+ -+ idlen = strlen(id); -+ kidlen = strlen(kid); -+ if (idlen > kidlen) -+ return 0; -+ -+ kid += kidlen - idlen; -+ if (strcasecmp(id, kid) != 0) -+ return 0; -+ -+ if (speclen == 2 && -+ memcmp(spec, "id", 2) == 0) -+ return 1; -+ -+ if (speclen == subtype->name_len && -+ memcmp(spec, subtype->name, speclen) == 0) -+ return 1; -+ -+ return 0; -+} -+ -+/* -+ * Describe the asymmetric key -+ */ -+static void asymmetric_key_describe(const struct key *key, struct seq_file *m) -+{ -+ const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); -+ const char *kid = asymmetric_key_id(key); -+ size_t n; -+ -+ seq_puts(m, key->description); -+ -+ if (subtype) { -+ seq_puts(m, ": "); -+ subtype->describe(key, m); -+ -+ if (kid) { -+ seq_putc(m, ' '); -+ n = strlen(kid); -+ if (n <= 8) -+ seq_puts(m, kid); -+ else -+ seq_puts(m, kid + n - 8); -+ } -+ -+ seq_puts(m, " ["); -+ /* put something here to indicate the key's capabilities */ -+ seq_putc(m, ']'); -+ } -+} -+ -+/* -+ * Instantiate a asymmetric_key defined key. The key was preparsed, so we just -+ * have to transfer the data here. -+ */ -+static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) -+{ -+ return -EOPNOTSUPP; -+} -+ -+/* -+ * dispose of the data dangling from the corpse of a asymmetric key -+ */ -+static void asymmetric_key_destroy(struct key *key) -+{ -+ struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); -+ if (subtype) { -+ subtype->destroy(key->payload.data); -+ module_put(subtype->owner); -+ key->type_data.p[0] = NULL; -+ } -+ kfree(key->type_data.p[1]); -+ key->type_data.p[1] = NULL; -+} -+ -+struct key_type key_type_asymmetric = { -+ .name = "asymmetric", -+ .instantiate = asymmetric_key_instantiate, -+ .match = asymmetric_key_match, -+ .destroy = asymmetric_key_destroy, -+ .describe = asymmetric_key_describe, -+}; -+EXPORT_SYMBOL_GPL(key_type_asymmetric); -+ -+/* -+ * Module stuff -+ */ -+static int __init asymmetric_key_init(void) -+{ -+ return register_key_type(&key_type_asymmetric); -+} -+ -+static void __exit asymmetric_key_cleanup(void) -+{ -+ unregister_key_type(&key_type_asymmetric); -+} -+ -+module_init(asymmetric_key_init); -+module_exit(asymmetric_key_cleanup); -diff --git a/include/keys/asymmetric-subtype.h b/include/keys/asymmetric-subtype.h -new file mode 100644 -index 0000000..4b840e8 ---- /dev/null -+++ b/include/keys/asymmetric-subtype.h -@@ -0,0 +1,55 @@ -+/* Asymmetric public-key cryptography key subtype -+ * -+ * See Documentation/security/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#ifndef _KEYS_ASYMMETRIC_SUBTYPE_H -+#define _KEYS_ASYMMETRIC_SUBTYPE_H -+ -+#include <linux/seq_file.h> -+#include <keys/asymmetric-type.h> -+ -+struct public_key_signature; -+ -+/* -+ * Keys of this type declare a subtype that indicates the handlers and -+ * capabilities. -+ */ -+struct asymmetric_key_subtype { -+ struct module *owner; -+ const char *name; -+ unsigned short name_len; /* length of name */ -+ -+ /* Describe a key of this subtype for /proc/keys */ -+ void (*describe)(const struct key *key, struct seq_file *m); -+ -+ /* Destroy a key of this subtype */ -+ void (*destroy)(void *payload); -+ -+ /* Verify the signature on a key of this subtype (optional) */ -+ int (*verify_signature)(const struct key *key, -+ const struct public_key_signature *sig); -+}; -+ -+/** -+ * asymmetric_key_subtype - Get the subtype from an asymmetric key -+ * @key: The key of interest. -+ * -+ * Retrieves and returns the subtype pointer of the asymmetric key from the -+ * type-specific data attached to the key. -+ */ -+static inline -+struct asymmetric_key_subtype *asymmetric_key_subtype(const struct key *key) -+{ -+ return key->type_data.p[0]; -+} -+ -+#endif /* _KEYS_ASYMMETRIC_SUBTYPE_H */ -diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h -new file mode 100644 -index 0000000..7dd4734 ---- /dev/null -+++ b/include/keys/asymmetric-type.h -@@ -0,0 +1,25 @@ -+/* Asymmetric Public-key cryptography key type interface -+ * -+ * See Documentation/security/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#ifndef _KEYS_ASYMMETRIC_TYPE_H -+#define _KEYS_ASYMMETRIC_TYPE_H -+ -+#include <linux/key-type.h> -+ -+extern struct key_type key_type_asymmetric; -+ -+/* -+ * The payload is at the discretion of the subtype. -+ */ -+ -+#endif /* _KEYS_ASYMMETRIC_TYPE_H */ --- -1.7.12.1 - - -From 6ec62201b26995d57fbd457469314bfc5653f2a0 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Thu, 13 Sep 2012 15:17:32 +0100 -Subject: [PATCH 06/37] KEYS: Asymmetric key pluggable data parsers - -The instantiation data passed to the asymmetric key type are expected to be -formatted in some way, and there are several possible standard ways to format -the data. - -The two obvious standards are OpenPGP keys and X.509 certificates. The latter -is especially useful when dealing with UEFI, and the former might be useful -when dealing with, say, eCryptfs. - -Further, it might be desirable to provide formatted blobs that indicate -hardware is to be accessed to retrieve the keys or that the keys live -unretrievably in a hardware store, but that the keys can be used by means of -the hardware. - -From userspace, the keys can be loaded using the keyctl command, for example, -an X.509 binary certificate: - - keyctl padd asymmetric foo @s <dhowells.pem - -or a PGP key: - - keyctl padd asymmetric bar @s <dhowells.pub - -or a pointer into the contents of the TPM: - - keyctl add asymmetric zebra "TPM:04982390582905f8" @s - -Inside the kernel, pluggable parsers register themselves and then get to -examine the payload data to see if they can handle it. If they can, they get -to: - - (1) Propose a name for the key, to be used it the name is "" or NULL. - - (2) Specify the key subtype. - - (3) Provide the data for the subtype. - -The key type asks the parser to do its stuff before a key is allocated and thus -before the name is set. If successful, the parser stores the suggested data -into the key_preparsed_payload struct, which will be either used (if the key is -successfully created and instantiated or updated) or discarded. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - crypto/asymmetric_keys/asymmetric_type.c | 120 ++++++++++++++++++++++++++++++- - include/keys/asymmetric-parser.h | 37 ++++++++++ - 2 files changed, 156 insertions(+), 1 deletion(-) - create mode 100644 include/keys/asymmetric-parser.h - -diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c -index bfb0424..cf80765 100644 ---- a/crypto/asymmetric_keys/asymmetric_type.c -+++ b/crypto/asymmetric_keys/asymmetric_type.c -@@ -11,6 +11,7 @@ - * 2 of the Licence, or (at your option) any later version. - */ - #include <keys/asymmetric-subtype.h> -+#include <keys/asymmetric-parser.h> - #include <linux/seq_file.h> - #include <linux/module.h> - #include <linux/slab.h> -@@ -18,6 +19,9 @@ - - MODULE_LICENSE("GPL"); - -+static LIST_HEAD(asymmetric_key_parsers); -+static DECLARE_RWSEM(asymmetric_key_parsers_sem); -+ - /* - * Match asymmetric keys on (part of) their name - * We have some shorthand methods for matching keys. We allow: -@@ -107,12 +111,79 @@ static void asymmetric_key_describe(const struct key *key, struct seq_file *m) - } - - /* -+ * Preparse a asymmetric payload to get format the contents appropriately for the -+ * internal payload to cut down on the number of scans of the data performed. -+ * -+ * We also generate a proposed description from the contents of the key that -+ * can be used to name the key if the user doesn't want to provide one. -+ */ -+static int asymmetric_key_preparse(struct key_preparsed_payload *prep) -+{ -+ struct asymmetric_key_parser *parser; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ if (prep->datalen == 0) -+ return -EINVAL; -+ -+ down_read(&asymmetric_key_parsers_sem); -+ -+ ret = -EBADMSG; -+ list_for_each_entry(parser, &asymmetric_key_parsers, link) { -+ pr_debug("Trying parser '%s'\n", parser->name); -+ -+ ret = parser->parse(prep); -+ if (ret != -EBADMSG) { -+ pr_debug("Parser recognised the format (ret %d)\n", -+ ret); -+ break; -+ } -+ } -+ -+ up_read(&asymmetric_key_parsers_sem); -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; -+} -+ -+/* -+ * Clean up the preparse data -+ */ -+static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) -+{ -+ struct asymmetric_key_subtype *subtype = prep->type_data[0]; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ if (subtype) { -+ subtype->destroy(prep->payload); -+ module_put(subtype->owner); -+ } -+ kfree(prep->type_data[1]); -+ kfree(prep->description); -+} -+ -+/* - * Instantiate a asymmetric_key defined key. The key was preparsed, so we just - * have to transfer the data here. - */ - static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { -- return -EOPNOTSUPP; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ ret = key_payload_reserve(key, prep->quotalen); -+ if (ret == 0) { -+ key->type_data.p[0] = prep->type_data[0]; -+ key->type_data.p[1] = prep->type_data[1]; -+ key->payload.data = prep->payload; -+ prep->type_data[0] = NULL; -+ prep->type_data[1] = NULL; -+ prep->payload = NULL; -+ } -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; - } - - /* -@@ -132,6 +203,8 @@ static void asymmetric_key_destroy(struct key *key) - - struct key_type key_type_asymmetric = { - .name = "asymmetric", -+ .preparse = asymmetric_key_preparse, -+ .free_preparse = asymmetric_key_free_preparse, - .instantiate = asymmetric_key_instantiate, - .match = asymmetric_key_match, - .destroy = asymmetric_key_destroy, -@@ -139,6 +212,51 @@ struct key_type key_type_asymmetric = { - }; - EXPORT_SYMBOL_GPL(key_type_asymmetric); - -+/** -+ * register_asymmetric_key_parser - Register a asymmetric key blob parser -+ * @parser: The parser to register -+ */ -+int register_asymmetric_key_parser(struct asymmetric_key_parser *parser) -+{ -+ struct asymmetric_key_parser *cursor; -+ int ret; -+ -+ down_write(&asymmetric_key_parsers_sem); -+ -+ list_for_each_entry(cursor, &asymmetric_key_parsers, link) { -+ if (strcmp(cursor->name, parser->name) == 0) { -+ pr_err("Asymmetric key parser '%s' already registered\n", -+ parser->name); -+ ret = -EEXIST; -+ goto out; -+ } -+ } -+ -+ list_add_tail(&parser->link, &asymmetric_key_parsers); -+ -+ pr_notice("Asymmetric key parser '%s' registered\n", parser->name); -+ ret = 0; -+ -+out: -+ up_write(&asymmetric_key_parsers_sem); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(register_asymmetric_key_parser); -+ -+/** -+ * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser -+ * @parser: The parser to unregister -+ */ -+void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser) -+{ -+ down_write(&asymmetric_key_parsers_sem); -+ list_del(&parser->link); -+ up_write(&asymmetric_key_parsers_sem); -+ -+ pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name); -+} -+EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser); -+ - /* - * Module stuff - */ -diff --git a/include/keys/asymmetric-parser.h b/include/keys/asymmetric-parser.h -new file mode 100644 -index 0000000..09b3b48 ---- /dev/null -+++ b/include/keys/asymmetric-parser.h -@@ -0,0 +1,37 @@ -+/* Asymmetric public-key cryptography data parser -+ * -+ * See Documentation/crypto/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#ifndef _KEYS_ASYMMETRIC_PARSER_H -+#define _KEYS_ASYMMETRIC_PARSER_H -+ -+/* -+ * Key data parser. Called during key instantiation. -+ */ -+struct asymmetric_key_parser { -+ struct list_head link; -+ struct module *owner; -+ const char *name; -+ -+ /* Attempt to parse a key from the data blob passed to add_key() or -+ * keyctl_instantiate(). Should also generate a proposed description -+ * that the caller can optionally use for the key. -+ * -+ * Return EBADMSG if not recognised. -+ */ -+ int (*parse)(struct key_preparsed_payload *prep); -+}; -+ -+extern int register_asymmetric_key_parser(struct asymmetric_key_parser *); -+extern void unregister_asymmetric_key_parser(struct asymmetric_key_parser *); -+ -+#endif /* _KEYS_ASYMMETRIC_PARSER_H */ --- -1.7.12.1 - - -From 390ad626607322c6e4da8a2e6d2a4094e78b919a Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 21 Sep 2012 23:24:55 +0100 -Subject: [PATCH 07/37] KEYS: Asymmetric public-key algorithm crypto key - subtype - -Add a subtype for supporting asymmetric public-key encryption algorithms such -as DSA (FIPS-186) and RSA (PKCS#1 / RFC1337). - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - crypto/asymmetric_keys/Kconfig | 8 +++ - crypto/asymmetric_keys/Makefile | 2 + - crypto/asymmetric_keys/public_key.c | 108 ++++++++++++++++++++++++++++++++++++ - crypto/asymmetric_keys/public_key.h | 28 ++++++++++ - include/crypto/public_key.h | 104 ++++++++++++++++++++++++++++++++++ - 5 files changed, 250 insertions(+) - create mode 100644 crypto/asymmetric_keys/public_key.c - create mode 100644 crypto/asymmetric_keys/public_key.h - create mode 100644 include/crypto/public_key.h - -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -index cad29b3..bbfccaa 100644 ---- a/crypto/asymmetric_keys/Kconfig -+++ b/crypto/asymmetric_keys/Kconfig -@@ -9,5 +9,13 @@ menuconfig ASYMMETRIC_KEY_TYPE - - if ASYMMETRIC_KEY_TYPE - -+config ASYMMETRIC_PUBLIC_KEY_SUBTYPE -+ tristate "Asymmetric public-key crypto algorithm subtype" -+ select MPILIB -+ help -+ This option provides support for asymmetric public key type handling. -+ If signature generation and/or verification are to be used, -+ appropriate hash algorithms (such as SHA-1) must be available. -+ ENOPKG will be reported if the requisite algorithm is unavailable. - - endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index b725bcc..5ed46ee 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -5,3 +5,5 @@ - obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o - - asymmetric_keys-y := asymmetric_type.o -+ -+obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o -diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c -new file mode 100644 -index 0000000..cb2e291 ---- /dev/null -+++ b/crypto/asymmetric_keys/public_key.c -@@ -0,0 +1,108 @@ -+/* In-software asymmetric public-key crypto subtype -+ * -+ * See Documentation/crypto/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 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) "PKEY: "fmt -+#include <linux/module.h> -+#include <linux/export.h> -+#include <linux/kernel.h> -+#include <linux/slab.h> -+#include <linux/seq_file.h> -+#include <keys/asymmetric-subtype.h> -+#include "public_key.h" -+ -+MODULE_LICENSE("GPL"); -+ -+const char *const pkey_algo[PKEY_ALGO__LAST] = { -+ [PKEY_ALGO_DSA] = "DSA", -+ [PKEY_ALGO_RSA] = "RSA", -+}; -+EXPORT_SYMBOL_GPL(pkey_algo); -+ -+const char *const pkey_hash_algo[PKEY_HASH__LAST] = { -+ [PKEY_HASH_MD4] = "md4", -+ [PKEY_HASH_MD5] = "md5", -+ [PKEY_HASH_SHA1] = "sha1", -+ [PKEY_HASH_RIPE_MD_160] = "rmd160", -+ [PKEY_HASH_SHA256] = "sha256", -+ [PKEY_HASH_SHA384] = "sha384", -+ [PKEY_HASH_SHA512] = "sha512", -+ [PKEY_HASH_SHA224] = "sha224", -+}; -+EXPORT_SYMBOL_GPL(pkey_hash_algo); -+ -+const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { -+ [PKEY_ID_PGP] = "PGP", -+ [PKEY_ID_X509] = "X509", -+}; -+EXPORT_SYMBOL_GPL(pkey_id_type); -+ -+/* -+ * Provide a part of a description of the key for /proc/keys. -+ */ -+static void public_key_describe(const struct key *asymmetric_key, -+ struct seq_file *m) -+{ -+ struct public_key *key = asymmetric_key->payload.data; -+ -+ if (key) -+ seq_printf(m, "%s.%s", -+ pkey_id_type[key->id_type], key->algo->name); -+} -+ -+/* -+ * Destroy a public key algorithm key. -+ */ -+void public_key_destroy(void *payload) -+{ -+ struct public_key *key = payload; -+ int i; -+ -+ if (key) { -+ for (i = 0; i < ARRAY_SIZE(key->mpi); i++) -+ mpi_free(key->mpi[i]); -+ kfree(key); -+ } -+} -+EXPORT_SYMBOL_GPL(public_key_destroy); -+ -+/* -+ * Verify a signature using a public key. -+ */ -+static int public_key_verify_signature(const struct key *key, -+ const struct public_key_signature *sig) -+{ -+ const struct public_key *pk = key->payload.data; -+ -+ if (!pk->algo->verify_signature) -+ return -ENOTSUPP; -+ -+ if (sig->nr_mpi != pk->algo->n_sig_mpi) { -+ pr_debug("Signature has %u MPI not %u\n", -+ sig->nr_mpi, pk->algo->n_sig_mpi); -+ return -EINVAL; -+ } -+ -+ return pk->algo->verify_signature(pk, sig); -+} -+ -+/* -+ * Public key algorithm asymmetric key subtype -+ */ -+struct asymmetric_key_subtype public_key_subtype = { -+ .owner = THIS_MODULE, -+ .name = "public_key", -+ .describe = public_key_describe, -+ .destroy = public_key_destroy, -+ .verify_signature = public_key_verify_signature, -+}; -+EXPORT_SYMBOL_GPL(public_key_subtype); -diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h -new file mode 100644 -index 0000000..1f86aad ---- /dev/null -+++ b/crypto/asymmetric_keys/public_key.h -@@ -0,0 +1,28 @@ -+/* Public key algorithm internals -+ * -+ * See Documentation/crypto/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#include <crypto/public_key.h> -+ -+extern struct asymmetric_key_subtype public_key_subtype; -+ -+/* -+ * Public key algorithm definition. -+ */ -+struct public_key_algorithm { -+ const char *name; -+ u8 n_pub_mpi; /* Number of MPIs in public key */ -+ u8 n_sec_mpi; /* Number of MPIs in secret key */ -+ u8 n_sig_mpi; /* Number of MPIs in a signature */ -+ int (*verify_signature)(const struct public_key *key, -+ const struct public_key_signature *sig); -+}; -diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h -new file mode 100644 -index 0000000..4b8b6c1 ---- /dev/null -+++ b/include/crypto/public_key.h -@@ -0,0 +1,104 @@ -+/* Asymmetric public-key algorithm definitions -+ * -+ * See Documentation/crypto/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#ifndef _LINUX_PUBLIC_KEY_H -+#define _LINUX_PUBLIC_KEY_H -+ -+#include <linux/mpi.h> -+ -+enum pkey_algo { -+ PKEY_ALGO_DSA, -+ PKEY_ALGO_RSA, -+ PKEY_ALGO__LAST -+}; -+ -+extern const char *const pkey_algo[PKEY_ALGO__LAST]; -+ -+enum pkey_hash_algo { -+ PKEY_HASH_MD4, -+ PKEY_HASH_MD5, -+ PKEY_HASH_SHA1, -+ PKEY_HASH_RIPE_MD_160, -+ PKEY_HASH_SHA256, -+ PKEY_HASH_SHA384, -+ PKEY_HASH_SHA512, -+ PKEY_HASH_SHA224, -+ PKEY_HASH__LAST -+}; -+ -+extern const char *const pkey_hash_algo[PKEY_HASH__LAST]; -+ -+enum pkey_id_type { -+ PKEY_ID_PGP, /* OpenPGP generated key ID */ -+ PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ -+ PKEY_ID_TYPE__LAST -+}; -+ -+extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST]; -+ -+/* -+ * Cryptographic data for the public-key subtype of the asymmetric key type. -+ * -+ * Note that this may include private part of the key as well as the public -+ * part. -+ */ -+struct public_key { -+ const struct public_key_algorithm *algo; -+ u8 capabilities; -+#define PKEY_CAN_ENCRYPT 0x01 -+#define PKEY_CAN_DECRYPT 0x02 -+#define PKEY_CAN_SIGN 0x04 -+#define PKEY_CAN_VERIFY 0x08 -+ enum pkey_id_type id_type : 8; -+ union { -+ MPI mpi[5]; -+ struct { -+ MPI p; /* DSA prime */ -+ MPI q; /* DSA group order */ -+ MPI g; /* DSA group generator */ -+ MPI y; /* DSA public-key value = g^x mod p */ -+ MPI x; /* DSA secret exponent (if present) */ -+ } dsa; -+ struct { -+ MPI n; /* RSA public modulus */ -+ MPI e; /* RSA public encryption exponent */ -+ MPI d; /* RSA secret encryption exponent (if present) */ -+ MPI p; /* RSA secret prime (if present) */ -+ MPI q; /* RSA secret prime (if present) */ -+ } rsa; -+ }; -+}; -+ -+extern void public_key_destroy(void *payload); -+ -+/* -+ * Public key cryptography signature data -+ */ -+struct public_key_signature { -+ u8 *digest; -+ u8 digest_size; /* Number of bytes in digest */ -+ u8 nr_mpi; /* Occupancy of mpi[] */ -+ enum pkey_hash_algo pkey_hash_algo : 8; -+ union { -+ MPI mpi[2]; -+ struct { -+ MPI s; /* m^d mod n */ -+ } rsa; -+ struct { -+ MPI r; -+ MPI s; -+ } dsa; -+ }; -+}; -+ -+#endif /* _LINUX_PUBLIC_KEY_H */ --- -1.7.12.1 - - -From 13d9a26663043faaa37dbe6c2f214ceef5f00b05 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 21 Sep 2012 23:25:04 +0100 -Subject: [PATCH 08/37] KEYS: Provide signature verification with an - asymmetric key - -Provide signature verification using an asymmetric-type key to indicate the -public key to be used. - -The API is a single function that can be found in crypto/public_key.h: - - int verify_signature(const struct key *key, - const struct public_key_signature *sig) - -The first argument is the appropriate key to be used and the second argument -is the parsed signature data: - - struct public_key_signature { - u8 *digest; - u16 digest_size; - enum pkey_hash_algo pkey_hash_algo : 8; - union { - MPI mpi[2]; - struct { - MPI s; /* m^d mod n */ - } rsa; - struct { - MPI r; - MPI s; - } dsa; - }; - }; - -This should be filled in prior to calling the function. The hash algorithm -should already have been called and the hash finalised and the output should -be in a buffer pointed to by the 'digest' member. - -Any extra data to be added to the hash by the hash format (eg. PGP) should -have been added by the caller prior to finalising the hash. - -It is assumed that the signature is made up of a number of MPI values. If an -algorithm becomes available for which this is not the case, the above structure -will have to change. - -It is also assumed that it will have been checked that the signature algorithm -matches the key algorithm. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - crypto/asymmetric_keys/Makefile | 2 +- - crypto/asymmetric_keys/signature.c | 49 ++++++++++++++++++++++++++++++++++++++ - include/crypto/public_key.h | 4 ++++ - 3 files changed, 54 insertions(+), 1 deletion(-) - create mode 100644 crypto/asymmetric_keys/signature.c - -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index 5ed46ee..8dcdf0c 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -4,6 +4,6 @@ - - obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o - --asymmetric_keys-y := asymmetric_type.o -+asymmetric_keys-y := asymmetric_type.o signature.o - - obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o -diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c -new file mode 100644 -index 0000000..50b3f88 ---- /dev/null -+++ b/crypto/asymmetric_keys/signature.c -@@ -0,0 +1,49 @@ -+/* Signature verification with an asymmetric key -+ * -+ * See Documentation/security/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#include <keys/asymmetric-subtype.h> -+#include <linux/module.h> -+#include <linux/err.h> -+#include <crypto/public_key.h> -+#include "asymmetric_keys.h" -+ -+/** -+ * verify_signature - Initiate the use of an asymmetric key to verify a signature -+ * @key: The asymmetric key to verify against -+ * @sig: The signature to check -+ * -+ * Returns 0 if successful or else an error. -+ */ -+int verify_signature(const struct key *key, -+ const struct public_key_signature *sig) -+{ -+ const struct asymmetric_key_subtype *subtype; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ if (key->type != &key_type_asymmetric) -+ return -EINVAL; -+ subtype = asymmetric_key_subtype(key); -+ if (!subtype || -+ !key->payload.data) -+ return -EINVAL; -+ if (!subtype->verify_signature) -+ return -ENOTSUPP; -+ -+ ret = subtype->verify_signature(key, sig); -+ -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(verify_signature); -diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h -index 4b8b6c1..f5b0224 100644 ---- a/include/crypto/public_key.h -+++ b/include/crypto/public_key.h -@@ -101,4 +101,8 @@ struct public_key_signature { - }; - }; - -+struct key; -+extern int verify_signature(const struct key *key, -+ const struct public_key_signature *sig); -+ - #endif /* _LINUX_PUBLIC_KEY_H */ --- -1.7.12.1 - - -From 3d379de76f21782c611b7d409d7374b82bc90220 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 21 Sep 2012 23:25:22 +0100 -Subject: [PATCH 09/37] MPILIB: Reinstate mpi_cmp[_ui]() and export for RSA - signature verification - -Reinstate and export mpi_cmp() and mpi_cmp_ui() from the MPI library for use by -RSA signature verification as per RFC3447 section 5.2.2 step 1. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - lib/mpi/Makefile | 1 + - lib/mpi/mpi-cmp.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 71 insertions(+) - create mode 100644 lib/mpi/mpi-cmp.c - -diff --git a/lib/mpi/Makefile b/lib/mpi/Makefile -index 45ca90a..019a68c 100644 ---- a/lib/mpi/Makefile -+++ b/lib/mpi/Makefile -@@ -14,6 +14,7 @@ mpi-y = \ - generic_mpih-add1.o \ - mpicoder.o \ - mpi-bit.o \ -+ mpi-cmp.o \ - mpih-cmp.o \ - mpih-div.o \ - mpih-mul.o \ -diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c -new file mode 100644 -index 0000000..1871e7b ---- /dev/null -+++ b/lib/mpi/mpi-cmp.c -@@ -0,0 +1,70 @@ -+/* mpi-cmp.c - MPI functions -+ * Copyright (C) 1998, 1999 Free Software Foundation, Inc. -+ * -+ * This file is part of GnuPG. -+ * -+ * GnuPG is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * GnuPG is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -+ */ -+ -+#include "mpi-internal.h" -+ -+int mpi_cmp_ui(MPI u, unsigned long v) -+{ -+ mpi_limb_t limb = v; -+ -+ mpi_normalize(u); -+ if (!u->nlimbs && !limb) -+ return 0; -+ if (u->sign) -+ return -1; -+ if (u->nlimbs > 1) -+ return 1; -+ -+ if (u->d[0] == limb) -+ return 0; -+ else if (u->d[0] > limb) -+ return 1; -+ else -+ return -1; -+} -+EXPORT_SYMBOL_GPL(mpi_cmp_ui); -+ -+int mpi_cmp(MPI u, MPI v) -+{ -+ mpi_size_t usize, vsize; -+ int cmp; -+ -+ mpi_normalize(u); -+ mpi_normalize(v); -+ usize = u->nlimbs; -+ vsize = v->nlimbs; -+ if (!u->sign && v->sign) -+ return 1; -+ if (u->sign && !v->sign) -+ return -1; -+ if (usize != vsize && !u->sign && !v->sign) -+ return usize - vsize; -+ if (usize != vsize && u->sign && v->sign) -+ return vsize + usize; -+ if (!usize) -+ return 0; -+ cmp = mpihelp_cmp(u->d, v->d, usize); -+ if (!cmp) -+ return 0; -+ if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0)) -+ return 1; -+ return -1; -+} -+EXPORT_SYMBOL_GPL(mpi_cmp); --- -1.7.12.1 - - -From b872c7db2ce34b5f051d1c38216843a1f796aa86 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 21 Sep 2012 23:25:40 +0100 -Subject: [PATCH 10/37] RSA: Implement signature verification algorithm - [PKCS#1 / RFC3447] - -Implement RSA public key cryptography [PKCS#1 / RFC3447]. At this time, only -the signature verification algorithm is supported. This uses the asymmetric -public key subtype to hold its key data. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - crypto/asymmetric_keys/Kconfig | 7 + - crypto/asymmetric_keys/Makefile | 1 + - crypto/asymmetric_keys/public_key.h | 2 + - crypto/asymmetric_keys/rsa.c | 269 ++++++++++++++++++++++++++++++++++++ - 4 files changed, 279 insertions(+) - create mode 100644 crypto/asymmetric_keys/rsa.c - -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -index bbfccaa..561759d 100644 ---- a/crypto/asymmetric_keys/Kconfig -+++ b/crypto/asymmetric_keys/Kconfig -@@ -18,4 +18,11 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE - appropriate hash algorithms (such as SHA-1) must be available. - ENOPKG will be reported if the requisite algorithm is unavailable. - -+config PUBLIC_KEY_ALGO_RSA -+ tristate "RSA public-key algorithm" -+ depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE -+ select MPILIB_EXTRA -+ help -+ This option enables support for the RSA algorithm (PKCS#1, RFC3447). -+ - endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index 8dcdf0c..7c92691 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -7,3 +7,4 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o - asymmetric_keys-y := asymmetric_type.o signature.o - - obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o -+obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o -diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h -index 1f86aad..5e5e356 100644 ---- a/crypto/asymmetric_keys/public_key.h -+++ b/crypto/asymmetric_keys/public_key.h -@@ -26,3 +26,5 @@ struct public_key_algorithm { - int (*verify_signature)(const struct public_key *key, - const struct public_key_signature *sig); - }; -+ -+extern const struct public_key_algorithm RSA_public_key_algorithm; -diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c -new file mode 100644 -index 0000000..9b31ee2 ---- /dev/null -+++ b/crypto/asymmetric_keys/rsa.c -@@ -0,0 +1,269 @@ -+/* RSA asymmetric public-key algorithm [RFC3447] -+ * -+ * Copyright (C) 2012 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) "RSA: "fmt -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/slab.h> -+#include "public_key.h" -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("RSA Public Key Algorithm"); -+ -+#define kenter(FMT, ...) \ -+ pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) -+#define kleave(FMT, ...) \ -+ pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) -+ -+/* -+ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2]. -+ */ -+static const u8 RSA_digest_info_MD5[] = { -+ 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, -+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */ -+ 0x05, 0x00, 0x04, 0x10 -+}; -+ -+static const u8 RSA_digest_info_SHA1[] = { -+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, -+ 0x2B, 0x0E, 0x03, 0x02, 0x1A, -+ 0x05, 0x00, 0x04, 0x14 -+}; -+ -+static const u8 RSA_digest_info_RIPE_MD_160[] = { -+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, -+ 0x2B, 0x24, 0x03, 0x02, 0x01, -+ 0x05, 0x00, 0x04, 0x14 -+}; -+ -+static const u8 RSA_digest_info_SHA224[] = { -+ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, -+ 0x05, 0x00, 0x04, 0x1C -+}; -+ -+static const u8 RSA_digest_info_SHA256[] = { -+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, -+ 0x05, 0x00, 0x04, 0x20 -+}; -+ -+static const u8 RSA_digest_info_SHA384[] = { -+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, -+ 0x05, 0x00, 0x04, 0x30 -+}; -+ -+static const u8 RSA_digest_info_SHA512[] = { -+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, -+ 0x05, 0x00, 0x04, 0x40 -+}; -+ -+static const struct { -+ const u8 *data; -+ size_t size; -+} RSA_ASN1_templates[PKEY_HASH__LAST] = { -+#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) } -+ [PKEY_HASH_MD5] = _(MD5), -+ [PKEY_HASH_SHA1] = _(SHA1), -+ [PKEY_HASH_RIPE_MD_160] = _(RIPE_MD_160), -+ [PKEY_HASH_SHA256] = _(SHA256), -+ [PKEY_HASH_SHA384] = _(SHA384), -+ [PKEY_HASH_SHA512] = _(SHA512), -+ [PKEY_HASH_SHA224] = _(SHA224), -+#undef _ -+}; -+ -+/* -+ * RSAVP1() function [RFC3447 sec 5.2.2] -+ */ -+static int RSAVP1(const struct public_key *key, MPI s, MPI *_m) -+{ -+ MPI m; -+ int ret; -+ -+ /* (1) Validate 0 <= s < n */ -+ if (mpi_cmp_ui(s, 0) < 0) { -+ kleave(" = -EBADMSG [s < 0]"); -+ return -EBADMSG; -+ } -+ if (mpi_cmp(s, key->rsa.n) >= 0) { -+ kleave(" = -EBADMSG [s >= n]"); -+ return -EBADMSG; -+ } -+ -+ m = mpi_alloc(0); -+ if (!m) -+ return -ENOMEM; -+ -+ /* (2) m = s^e mod n */ -+ ret = mpi_powm(m, s, key->rsa.e, key->rsa.n); -+ if (ret < 0) { -+ mpi_free(m); -+ return ret; -+ } -+ -+ *_m = m; -+ return 0; -+} -+ -+/* -+ * Integer to Octet String conversion [RFC3447 sec 4.1] -+ */ -+static int RSA_I2OSP(MPI x, size_t xLen, u8 **_X) -+{ -+ unsigned X_size, x_size; -+ int X_sign; -+ u8 *X; -+ -+ /* Make sure the string is the right length. The number should begin -+ * with { 0x00, 0x01, ... } so we have to account for 15 leading zero -+ * bits not being reported by MPI. -+ */ -+ x_size = mpi_get_nbits(x); -+ pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8); -+ if (x_size != xLen * 8 - 15) -+ return -ERANGE; -+ -+ X = mpi_get_buffer(x, &X_size, &X_sign); -+ if (!X) -+ return -ENOMEM; -+ if (X_sign < 0) { -+ kfree(X); -+ return -EBADMSG; -+ } -+ if (X_size != xLen - 1) { -+ kfree(X); -+ return -EBADMSG; -+ } -+ -+ *_X = X; -+ return 0; -+} -+ -+/* -+ * Perform the RSA signature verification. -+ * @H: Value of hash of data and metadata -+ * @EM: The computed signature value -+ * @k: The size of EM (EM[0] is an invalid location but should hold 0x00) -+ * @hash_size: The size of H -+ * @asn1_template: The DigestInfo ASN.1 template -+ * @asn1_size: Size of asm1_template[] -+ */ -+static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, -+ const u8 *asn1_template, size_t asn1_size) -+{ -+ unsigned PS_end, T_offset, i; -+ -+ kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size); -+ -+ if (k < 2 + 1 + asn1_size + hash_size) -+ return -EBADMSG; -+ -+ /* Decode the EMSA-PKCS1-v1_5 */ -+ if (EM[1] != 0x01) { -+ kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]); -+ return -EBADMSG; -+ } -+ -+ T_offset = k - (asn1_size + hash_size); -+ PS_end = T_offset - 1; -+ if (EM[PS_end] != 0x00) { -+ kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]); -+ return -EBADMSG; -+ } -+ -+ for (i = 2; i < PS_end; i++) { -+ if (EM[i] != 0xff) { -+ kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]); -+ return -EBADMSG; -+ } -+ } -+ -+ if (memcmp(asn1_template, EM + T_offset, asn1_size) != 0) { -+ kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]"); -+ return -EBADMSG; -+ } -+ -+ if (memcmp(H, EM + T_offset + asn1_size, hash_size) != 0) { -+ kleave(" = -EKEYREJECTED [EM[T] hash mismatch]"); -+ return -EKEYREJECTED; -+ } -+ -+ kleave(" = 0"); -+ return 0; -+} -+ -+/* -+ * Perform the verification step [RFC3447 sec 8.2.2]. -+ */ -+static int RSA_verify_signature(const struct public_key *key, -+ const struct public_key_signature *sig) -+{ -+ size_t tsize; -+ int ret; -+ -+ /* Variables as per RFC3447 sec 8.2.2 */ -+ const u8 *H = sig->digest; -+ u8 *EM = NULL; -+ MPI m = NULL; -+ size_t k; -+ -+ kenter(""); -+ -+ if (!RSA_ASN1_templates[sig->pkey_hash_algo].data) -+ return -ENOTSUPP; -+ -+ /* (1) Check the signature size against the public key modulus size */ -+ k = (mpi_get_nbits(key->rsa.n) + 7) / 8; -+ -+ tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; -+ pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); -+ if (tsize != k) { -+ ret = -EBADMSG; -+ goto error; -+ } -+ -+ /* (2b) Apply the RSAVP1 verification primitive to the public key */ -+ ret = RSAVP1(key, sig->rsa.s, &m); -+ if (ret < 0) -+ goto error; -+ -+ /* (2c) Convert the message representative (m) to an encoded message -+ * (EM) of length k octets. -+ * -+ * NOTE! The leading zero byte is suppressed by MPI, so we pass a -+ * pointer to the _preceding_ byte to RSA_verify()! -+ */ -+ ret = RSA_I2OSP(m, k, &EM); -+ if (ret < 0) -+ goto error; -+ -+ ret = RSA_verify(H, EM - 1, k, sig->digest_size, -+ RSA_ASN1_templates[sig->pkey_hash_algo].data, -+ RSA_ASN1_templates[sig->pkey_hash_algo].size); -+ -+error: -+ kfree(EM); -+ mpi_free(m); -+ kleave(" = %d", ret); -+ return ret; -+} -+ -+const struct public_key_algorithm RSA_public_key_algorithm = { -+ .name = "RSA", -+ .n_pub_mpi = 2, -+ .n_sec_mpi = 3, -+ .n_sig_mpi = 1, -+ .verify_signature = RSA_verify_signature, -+}; -+EXPORT_SYMBOL_GPL(RSA_public_key_algorithm); --- -1.7.12.1 - - -From 362af238a35e095094b3f5a228cf2c0f60c10cd9 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 21 Sep 2012 23:28:05 +0100 -Subject: [PATCH 11/37] RSA: Fix signature verification for shorter signatures - -gpg can produce a signature file where length of signature is less than the -modulus size because the amount of space an MPI takes up is kept as low as -possible by discarding leading zeros. This regularly happens for several -modules during the build. - -Fix it by relaxing check in RSA verification code. - -Thanks to Tomas Mraz and Miloslav Trmac for help. - -Signed-off-by: Milan Broz <mbroz@redhat.com> -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - crypto/asymmetric_keys/rsa.c | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - -diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c -index 9b31ee2..4a6a069 100644 ---- a/crypto/asymmetric_keys/rsa.c -+++ b/crypto/asymmetric_keys/rsa.c -@@ -224,15 +224,23 @@ static int RSA_verify_signature(const struct public_key *key, - return -ENOTSUPP; - - /* (1) Check the signature size against the public key modulus size */ -- k = (mpi_get_nbits(key->rsa.n) + 7) / 8; -+ k = mpi_get_nbits(key->rsa.n); -+ tsize = mpi_get_nbits(sig->rsa.s); - -- tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; -+ /* According to RFC 4880 sec 3.2, length of MPI is computed starting -+ * from most significant bit. So the RFC 3447 sec 8.2.2 size check -+ * must be relaxed to conform with shorter signatures - so we fail here -+ * only if signature length is longer than modulus size. -+ */ - pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); -- if (tsize != k) { -+ if (k < tsize) { - ret = -EBADMSG; - goto error; - } - -+ /* Round up and convert to octets */ -+ k = (k + 7) / 8; -+ - /* (2b) Apply the RSAVP1 verification primitive to the public key */ - ret = RSAVP1(key, sig->rsa.s, &m); - if (ret < 0) --- -1.7.12.1 - - -From 81451f08c7db892e06144cf3bc89746e68269624 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 21 Sep 2012 23:30:46 +0100 -Subject: [PATCH 12/37] X.509: Implement simple static OID registry - -Implement a simple static OID registry that allows the mapping of an encoded -OID to an enum value for ease of use. - -The OID registry index enum appears in the: - - linux/oid_registry.h - -header file. A script generates the registry from lines in the header file -that look like: - - <sp*>OID_foo,<sp*>/*<sp*>1.2.3.4<sp*>*/ - -The actual OID is taken to be represented by the numbers with interpolated -dots in the comment. - -All other lines in the header are ignored. - -The registry is queries by calling: - - OID look_up_oid(const void *data, size_t datasize); - -This returns a number from the registry enum representing the OID if found or -OID__NR if not. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - include/linux/oid_registry.h | 90 +++++++++++++++++++ - lib/.gitignore | 2 +- - lib/Kconfig | 5 ++ - lib/Makefile | 16 ++++ - lib/build_OID_registry | 209 +++++++++++++++++++++++++++++++++++++++++++ - lib/oid_registry.c | 89 ++++++++++++++++++ - 6 files changed, 410 insertions(+), 1 deletion(-) - create mode 100644 include/linux/oid_registry.h - create mode 100755 lib/build_OID_registry - create mode 100644 lib/oid_registry.c - -diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h -new file mode 100644 -index 0000000..5928546 ---- /dev/null -+++ b/include/linux/oid_registry.h -@@ -0,0 +1,90 @@ -+/* ASN.1 Object identifier (OID) registry -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#ifndef _LINUX_OID_REGISTRY_H -+#define _LINUX_OID_REGISTRY_H -+ -+#include <linux/types.h> -+ -+/* -+ * OIDs are turned into these values if possible, or OID__NR if not held here. -+ * -+ * NOTE! Do not mess with the format of each line as this is read by -+ * build_OID_registry.pl to generate the data for look_up_OID(). -+ */ -+enum OID { -+ OID_id_dsa_with_sha1, /* 1.2.840.10030.4.3 */ -+ OID_id_dsa, /* 1.2.840.10040.4.1 */ -+ OID_id_ecdsa_with_sha1, /* 1.2.840.10045.4.1 */ -+ OID_id_ecPublicKey, /* 1.2.840.10045.2.1 */ -+ -+ /* PKCS#1 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)} */ -+ OID_rsaEncryption, /* 1.2.840.113549.1.1.1 */ -+ OID_md2WithRSAEncryption, /* 1.2.840.113549.1.1.2 */ -+ OID_md3WithRSAEncryption, /* 1.2.840.113549.1.1.3 */ -+ OID_md4WithRSAEncryption, /* 1.2.840.113549.1.1.4 */ -+ OID_sha1WithRSAEncryption, /* 1.2.840.113549.1.1.5 */ -+ OID_sha256WithRSAEncryption, /* 1.2.840.113549.1.1.11 */ -+ OID_sha384WithRSAEncryption, /* 1.2.840.113549.1.1.12 */ -+ OID_sha512WithRSAEncryption, /* 1.2.840.113549.1.1.13 */ -+ OID_sha224WithRSAEncryption, /* 1.2.840.113549.1.1.14 */ -+ /* PKCS#7 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7)} */ -+ OID_data, /* 1.2.840.113549.1.7.1 */ -+ OID_signed_data, /* 1.2.840.113549.1.7.2 */ -+ /* PKCS#9 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)} */ -+ OID_email_address, /* 1.2.840.113549.1.9.1 */ -+ OID_content_type, /* 1.2.840.113549.1.9.3 */ -+ OID_messageDigest, /* 1.2.840.113549.1.9.4 */ -+ OID_signingTime, /* 1.2.840.113549.1.9.5 */ -+ OID_smimeCapabilites, /* 1.2.840.113549.1.9.15 */ -+ OID_smimeAuthenticatedAttrs, /* 1.2.840.113549.1.9.16.2.11 */ -+ -+ /* {iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2)} */ -+ OID_md2, /* 1.2.840.113549.2.2 */ -+ OID_md4, /* 1.2.840.113549.2.4 */ -+ OID_md5, /* 1.2.840.113549.2.5 */ -+ -+ OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ -+ OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ -+ OID_sha1, /* 1.3.14.3.2.26 */ -+ -+ /* Distinguished Name attribute IDs [RFC 2256] */ -+ OID_commonName, /* 2.5.4.3 */ -+ OID_surname, /* 2.5.4.4 */ -+ OID_countryName, /* 2.5.4.6 */ -+ OID_locality, /* 2.5.4.7 */ -+ OID_stateOrProvinceName, /* 2.5.4.8 */ -+ OID_organizationName, /* 2.5.4.10 */ -+ OID_organizationUnitName, /* 2.5.4.11 */ -+ OID_title, /* 2.5.4.12 */ -+ OID_description, /* 2.5.4.13 */ -+ OID_name, /* 2.5.4.41 */ -+ OID_givenName, /* 2.5.4.42 */ -+ OID_initials, /* 2.5.4.43 */ -+ OID_generationalQualifier, /* 2.5.4.44 */ -+ -+ /* Certificate extension IDs */ -+ OID_subjectKeyIdentifier, /* 2.5.29.14 */ -+ OID_keyUsage, /* 2.5.29.15 */ -+ OID_subjectAltName, /* 2.5.29.17 */ -+ OID_issuerAltName, /* 2.5.29.18 */ -+ OID_basicConstraints, /* 2.5.29.19 */ -+ OID_crlDistributionPoints, /* 2.5.29.31 */ -+ OID_certPolicies, /* 2.5.29.32 */ -+ OID_authorityKeyIdentifier, /* 2.5.29.35 */ -+ OID_extKeyUsage, /* 2.5.29.37 */ -+ -+ OID__NR -+}; -+ -+extern enum OID look_up_OID(const void *data, size_t datasize); -+ -+#endif /* _LINUX_OID_REGISTRY_H */ -diff --git a/lib/.gitignore b/lib/.gitignore -index 3bef1ea..09aae85 100644 ---- a/lib/.gitignore -+++ b/lib/.gitignore -@@ -3,4 +3,4 @@ - # - gen_crc32table - crc32table.h -- -+oid_registry_data.c -diff --git a/lib/Kconfig b/lib/Kconfig -index bb94c1b..4b31a46 100644 ---- a/lib/Kconfig -+++ b/lib/Kconfig -@@ -396,4 +396,9 @@ config SIGNATURE - config LIBFDT - bool - -+config OID_REGISTRY -+ tristate -+ help -+ Enable fast lookup object identifier registry. -+ - endmenu -diff --git a/lib/Makefile b/lib/Makefile -index 42d283e..b042896 100644 ---- a/lib/Makefile -+++ b/lib/Makefile -@@ -150,3 +150,19 @@ quiet_cmd_crc32 = GEN $@ - - $(obj)/crc32table.h: $(obj)/gen_crc32table - $(call cmd,crc32) -+ -+# -+# Build a fast OID lookip registry from include/linux/oid_registry.h -+# -+obj-$(CONFIG_OID_REGISTRY) += oid_registry.o -+ -+$(obj)/oid_registry.c: $(obj)/oid_registry_data.c -+ -+$(obj)/oid_registry_data.c: $(srctree)/include/linux/oid_registry.h \ -+ $(src)/build_OID_registry -+ $(call cmd,build_OID_registry) -+ -+quiet_cmd_build_OID_registry = GEN $@ -+ cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@ -+ -+clean-files += oid_registry_data.c -diff --git a/lib/build_OID_registry b/lib/build_OID_registry -new file mode 100755 -index 0000000..dfbdaab ---- /dev/null -+++ b/lib/build_OID_registry -@@ -0,0 +1,209 @@ -+#!/usr/bin/perl -w -+# -+# Build a static ASN.1 Object Identified (OID) registry -+# -+# Copyright (C) 2012 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. -+# -+ -+use strict; -+ -+my @names = (); -+my @oids = (); -+ -+if ($#ARGV != 1) { -+ print STDERR "Format: ", $0, " <in-h-file> <out-c-file>\n"; -+ exit(2); -+} -+ -+# -+# Open the file to read from -+# -+open IN_FILE, "<$ARGV[0]" || die; -+while (<IN_FILE>) { -+ chomp; -+ if (m!\s+OID_([a-zA-z][a-zA-Z0-9_]+),\s+/[*]\s+([012][.0-9]*)\s+[*]/!) { -+ push @names, $1; -+ push @oids, $2; -+ } -+} -+close IN_FILE || die; -+ -+# -+# Open the files to write into -+# -+open C_FILE, ">$ARGV[1]" or die; -+print C_FILE "/*\n"; -+print C_FILE " * Automatically generated by ", $0, ". Do not edit\n"; -+print C_FILE " */\n"; -+ -+# -+# Split the data up into separate lists and also determine the lengths of the -+# encoded data arrays. -+# -+my @indices = (); -+my @lengths = (); -+my $total_length = 0; -+ -+print "Compiling ", $#names + 1, " OIDs\n"; -+ -+for (my $i = 0; $i <= $#names; $i++) { -+ my $name = $names[$i]; -+ my $oid = $oids[$i]; -+ -+ my @components = split(/[.]/, $oid); -+ -+ # Determine the encoded length of this OID -+ my $size = $#components; -+ for (my $loop = 2; $loop <= $#components; $loop++) { -+ my $c = $components[$loop]; -+ -+ # We will base128 encode the number -+ my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); -+ $tmp = int($tmp / 7); -+ $size += $tmp; -+ } -+ push @lengths, $size; -+ push @indices, $total_length; -+ $total_length += $size; -+} -+ -+# -+# Emit the look-up-by-OID index table -+# -+print C_FILE "\n"; -+if ($total_length <= 255) { -+ print C_FILE "static const unsigned char oid_index[OID__NR + 1] = {\n"; -+} else { -+ print C_FILE "static const unsigned short oid_index[OID__NR + 1] = {\n"; -+} -+for (my $i = 0; $i <= $#names; $i++) { -+ print C_FILE "\t[OID_", $names[$i], "] = ", $indices[$i], ",\n" -+} -+print C_FILE "\t[OID__NR] = ", $total_length, "\n"; -+print C_FILE "};\n"; -+ -+# -+# Encode the OIDs -+# -+my @encoded_oids = (); -+ -+for (my $i = 0; $i <= $#names; $i++) { -+ my @octets = (); -+ -+ my @components = split(/[.]/, $oids[$i]); -+ -+ push @octets, $components[0] * 40 + $components[1]; -+ -+ for (my $loop = 2; $loop <= $#components; $loop++) { -+ my $c = $components[$loop]; -+ -+ # Base128 encode the number -+ my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); -+ $tmp = int($tmp / 7); -+ -+ for (; $tmp > 0; $tmp--) { -+ push @octets, (($c >> $tmp * 7) & 0x7f) | 0x80; -+ } -+ push @octets, $c & 0x7f; -+ } -+ -+ push @encoded_oids, \@octets; -+} -+ -+# -+# Create a hash value for each OID -+# -+my @hash_values = (); -+for (my $i = 0; $i <= $#names; $i++) { -+ my @octets = @{$encoded_oids[$i]}; -+ -+ my $hash = $#octets; -+ foreach (@octets) { -+ $hash += $_ * 33; -+ } -+ -+ $hash = ($hash >> 24) ^ ($hash >> 16) ^ ($hash >> 8) ^ ($hash); -+ -+ push @hash_values, $hash & 0xff; -+} -+ -+# -+# Emit the OID data -+# -+print C_FILE "\n"; -+print C_FILE "static const unsigned char oid_data[", $total_length, "] = {\n"; -+for (my $i = 0; $i <= $#names; $i++) { -+ my @octets = @{$encoded_oids[$i]}; -+ print C_FILE "\t"; -+ print C_FILE $_, ", " foreach (@octets); -+ print C_FILE "\t// ", $names[$i]; -+ print C_FILE "\n"; -+} -+print C_FILE "};\n"; -+ -+# -+# Build the search index table (ordered by length then hash then content) -+# -+my @index_table = ( 0 .. $#names ); -+ -+@index_table = sort { -+ my @octets_a = @{$encoded_oids[$a]}; -+ my @octets_b = @{$encoded_oids[$b]}; -+ -+ return $hash_values[$a] <=> $hash_values[$b] -+ if ($hash_values[$a] != $hash_values[$b]); -+ return $#octets_a <=> $#octets_b -+ if ($#octets_a != $#octets_b); -+ for (my $i = $#octets_a; $i >= 0; $i--) { -+ return $octets_a[$i] <=> $octets_b[$i] -+ if ($octets_a[$i] != $octets_b[$i]); -+ } -+ return 0; -+ -+} @index_table; -+ -+# -+# Emit the search index and hash value table -+# -+print C_FILE "\n"; -+print C_FILE "static const struct {\n"; -+print C_FILE "\tunsigned char hash;\n"; -+if ($#names <= 255) { -+ print C_FILE "\tenum OID oid : 8;\n"; -+} else { -+ print C_FILE "\tenum OID oid : 16;\n"; -+} -+print C_FILE "} oid_search_table[OID__NR] = {\n"; -+for (my $i = 0; $i <= $#names; $i++) { -+ my @octets = @{$encoded_oids[$index_table[$i]]}; -+ printf(C_FILE "\t[%3u] = { %3u, OID_%-35s }, // ", -+ $i, -+ $hash_values[$index_table[$i]], -+ $names[$index_table[$i]]); -+ printf C_FILE "%02x", $_ foreach (@octets); -+ print C_FILE "\n"; -+} -+print C_FILE "};\n"; -+ -+# -+# Emit the OID debugging name table -+# -+#print C_FILE "\n"; -+#print C_FILE "const char *const oid_name_table[OID__NR + 1] = {\n"; -+# -+#for (my $i = 0; $i <= $#names; $i++) { -+# print C_FILE "\t\"", $names[$i], "\",\n" -+#} -+#print C_FILE "\t\"Unknown-OID\"\n"; -+#print C_FILE "};\n"; -+ -+# -+# Polish off -+# -+close C_FILE or die; -diff --git a/lib/oid_registry.c b/lib/oid_registry.c -new file mode 100644 -index 0000000..33cfd17 ---- /dev/null -+++ b/lib/oid_registry.c -@@ -0,0 +1,89 @@ -+/* ASN.1 Object identifier (OID) registry -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#include <linux/export.h> -+#include <linux/oid_registry.h> -+#include "oid_registry_data.c" -+ -+/** -+ * look_up_OID - Find an OID registration for the specified data -+ * @data: Binary representation of the OID -+ * @datasize: Size of the binary representation -+ */ -+enum OID look_up_OID(const void *data, size_t datasize) -+{ -+ const unsigned char *octets = data; -+ enum OID oid; -+ unsigned char xhash; -+ unsigned i, j, k, hash; -+ size_t len; -+ -+ /* Hash the OID data */ -+ hash = datasize - 1; -+ -+ for (i = 0; i < datasize; i++) -+ hash += octets[i] * 33; -+ hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash; -+ hash &= 0xff; -+ -+ /* Binary search the OID registry. OIDs are stored in ascending order -+ * of hash value then ascending order of size and then in ascending -+ * order of reverse value. -+ */ -+ i = 0; -+ k = OID__NR; -+ while (i < k) { -+ j = (i + k) / 2; -+ -+ xhash = oid_search_table[j].hash; -+ if (xhash > hash) { -+ k = j; -+ continue; -+ } -+ if (xhash < hash) { -+ i = j + 1; -+ continue; -+ } -+ -+ oid = oid_search_table[j].oid; -+ len = oid_index[oid + 1] - oid_index[oid]; -+ if (len > datasize) { -+ k = j; -+ continue; -+ } -+ if (len < datasize) { -+ i = j + 1; -+ continue; -+ } -+ -+ /* Variation is most likely to be at the tail end of the -+ * OID, so do the comparison in reverse. -+ */ -+ while (len > 0) { -+ unsigned char a = oid_data[oid_index[oid] + --len]; -+ unsigned char b = octets[len]; -+ if (a > b) { -+ k = j; -+ goto next; -+ } -+ if (a < b) { -+ i = j + 1; -+ goto next; -+ } -+ } -+ return oid; -+ next: -+ ; -+ } -+ -+ return OID__NR; -+} -+EXPORT_SYMBOL_GPL(look_up_OID); --- -1.7.12.1 - - -From 3e1b30d7c67fd5419d4f6eb5d10b557dda4bc4fd Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 21 Sep 2012 23:30:51 +0100 -Subject: [PATCH 13/37] X.509: Add utility functions to render OIDs as strings - -Add a pair of utility functions to render OIDs as strings. The first takes an -encoded OID and turns it into a "a.b.c.d" form string: - - int sprint_oid(const void *data, size_t datasize, - char *buffer, size_t bufsize); - -The second takes an OID enum index and calls the first on the data held -therein: - - int sprint_OID(enum OID oid, char *buffer, size_t bufsize); - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - include/linux/oid_registry.h | 2 ++ - lib/oid_registry.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 83 insertions(+) - -diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h -index 5928546..6926db7 100644 ---- a/include/linux/oid_registry.h -+++ b/include/linux/oid_registry.h -@@ -86,5 +86,7 @@ enum OID { - }; - - extern enum OID look_up_OID(const void *data, size_t datasize); -+extern int sprint_oid(const void *, size_t, char *, size_t); -+extern int sprint_OID(enum OID, char *, size_t); - - #endif /* _LINUX_OID_REGISTRY_H */ -diff --git a/lib/oid_registry.c b/lib/oid_registry.c -index 33cfd17..d8de11f 100644 ---- a/lib/oid_registry.c -+++ b/lib/oid_registry.c -@@ -11,6 +11,9 @@ - - #include <linux/export.h> - #include <linux/oid_registry.h> -+#include <linux/kernel.h> -+#include <linux/errno.h> -+#include <linux/bug.h> - #include "oid_registry_data.c" - - /** -@@ -87,3 +90,81 @@ enum OID look_up_OID(const void *data, size_t datasize) - return OID__NR; - } - EXPORT_SYMBOL_GPL(look_up_OID); -+ -+/* -+ * sprint_OID - Print an Object Identifier into a buffer -+ * @data: The encoded OID to print -+ * @datasize: The size of the encoded OID -+ * @buffer: The buffer to render into -+ * @bufsize: The size of the buffer -+ * -+ * The OID is rendered into the buffer in "a.b.c.d" format and the number of -+ * bytes is returned. -EBADMSG is returned if the data could not be intepreted -+ * and -ENOBUFS if the buffer was too small. -+ */ -+int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) -+{ -+ const unsigned char *v = data, *end = v + datasize; -+ unsigned long num; -+ unsigned char n; -+ size_t ret; -+ int count; -+ -+ if (v >= end) -+ return -EBADMSG; -+ -+ n = *v++; -+ ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40); -+ buffer += count; -+ bufsize -= count; -+ if (bufsize == 0) -+ return -ENOBUFS; -+ -+ while (v < end) { -+ num = 0; -+ n = *v++; -+ if (!(n & 0x80)) { -+ num = n; -+ } else { -+ num = n & 0x7f; -+ do { -+ if (v >= end) -+ return -EBADMSG; -+ n = *v++; -+ num <<= 7; -+ num |= n & 0x7f; -+ } while (n & 0x80); -+ } -+ ret += count = snprintf(buffer, bufsize, ".%lu", num); -+ buffer += count; -+ bufsize -= count; -+ if (bufsize == 0) -+ return -ENOBUFS; -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(sprint_oid); -+ -+/** -+ * sprint_OID - Print an Object Identifier into a buffer -+ * @oid: The OID to print -+ * @buffer: The buffer to render into -+ * @bufsize: The size of the buffer -+ * -+ * The OID is rendered into the buffer in "a.b.c.d" format and the number of -+ * bytes is returned. -+ */ -+int sprint_OID(enum OID oid, char *buffer, size_t bufsize) -+{ -+ int ret; -+ -+ BUG_ON(oid >= OID__NR); -+ -+ ret = sprint_oid(oid_data + oid_index[oid], -+ oid_index[oid + 1] - oid_index[oid], -+ buffer, bufsize); -+ BUG_ON(ret == -EBADMSG); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(sprint_OID); --- -1.7.12.1 - - -From 978cd19071f71ae6a0e622bb2521f88ea633a326 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 21 Sep 2012 23:31:13 +0100 -Subject: [PATCH 14/37] X.509: Add simple ASN.1 grammar compiler - -Add a simple ASN.1 grammar compiler. This produces a bytecode output that can -be fed to a decoder to inform the decoder how to interpret the ASN.1 stream it -is trying to parse. - -Action functions can be specified in the grammar by interpolating: - - ({ foo }) - -after a type, for example: - - SubjectPublicKeyInfo ::= SEQUENCE { - algorithm AlgorithmIdentifier, - subjectPublicKey BIT STRING ({ do_key_data }) - } - -The decoder is expected to call these after matching this type and parsing the -contents if it is a constructed type. - -The grammar compiler does not currently support the SET type (though it does -support SET OF) as I can't see a good way of tracking which members have been -encountered yet without using up extra stack space. - -Currently, the grammar compiler will fail if more than 256 bytes of bytecode -would be produced or more than 256 actions have been specified as it uses -8-bit jump values and action indices to keep space usage down. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - include/linux/asn1.h | 67 ++ - include/linux/asn1_ber_bytecode.h | 87 +++ - init/Kconfig | 8 + - scripts/.gitignore | 1 + - scripts/Makefile | 2 + - scripts/Makefile.build | 11 + - scripts/asn1_compiler.c | 1545 +++++++++++++++++++++++++++++++++++++ - 7 files changed, 1721 insertions(+) - create mode 100644 include/linux/asn1.h - create mode 100644 include/linux/asn1_ber_bytecode.h - create mode 100644 scripts/asn1_compiler.c - -diff --git a/include/linux/asn1.h b/include/linux/asn1.h -new file mode 100644 -index 0000000..5c3f4e4 ---- /dev/null -+++ b/include/linux/asn1.h -@@ -0,0 +1,67 @@ -+/* ASN.1 BER/DER/CER encoding definitions -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#ifndef _LINUX_ASN1_H -+#define _LINUX_ASN1_H -+ -+/* Class */ -+enum asn1_class { -+ ASN1_UNIV = 0, /* Universal */ -+ ASN1_APPL = 1, /* Application */ -+ ASN1_CONT = 2, /* Context */ -+ ASN1_PRIV = 3 /* Private */ -+}; -+#define ASN1_CLASS_BITS 0xc0 -+ -+ -+enum asn1_method { -+ ASN1_PRIM = 0, /* Primitive */ -+ ASN1_CONS = 1 /* Constructed */ -+}; -+#define ASN1_CONS_BIT 0x20 -+ -+/* Tag */ -+enum asn1_tag { -+ ASN1_EOC = 0, /* End Of Contents or N/A */ -+ ASN1_BOOL = 1, /* Boolean */ -+ ASN1_INT = 2, /* Integer */ -+ ASN1_BTS = 3, /* Bit String */ -+ ASN1_OTS = 4, /* Octet String */ -+ ASN1_NULL = 5, /* Null */ -+ ASN1_OID = 6, /* Object Identifier */ -+ ASN1_ODE = 7, /* Object Description */ -+ ASN1_EXT = 8, /* External */ -+ ASN1_REAL = 9, /* Real float */ -+ ASN1_ENUM = 10, /* Enumerated */ -+ ASN1_EPDV = 11, /* Embedded PDV */ -+ ASN1_UTF8STR = 12, /* UTF8 String */ -+ ASN1_RELOID = 13, /* Relative OID */ -+ /* 14 - Reserved */ -+ /* 15 - Reserved */ -+ ASN1_SEQ = 16, /* Sequence and Sequence of */ -+ ASN1_SET = 17, /* Set and Set of */ -+ ASN1_NUMSTR = 18, /* Numerical String */ -+ ASN1_PRNSTR = 19, /* Printable String */ -+ ASN1_TEXSTR = 20, /* T61 String / Teletext String */ -+ ASN1_VIDSTR = 21, /* Videotex String */ -+ ASN1_IA5STR = 22, /* IA5 String */ -+ ASN1_UNITIM = 23, /* Universal Time */ -+ ASN1_GENTIM = 24, /* General Time */ -+ ASN1_GRASTR = 25, /* Graphic String */ -+ ASN1_VISSTR = 26, /* Visible String */ -+ ASN1_GENSTR = 27, /* General String */ -+ ASN1_UNISTR = 28, /* Universal String */ -+ ASN1_CHRSTR = 29, /* Character String */ -+ ASN1_BMPSTR = 30, /* BMP String */ -+ ASN1_LONG_TAG = 31 /* Long form tag */ -+}; -+ -+#endif /* _LINUX_ASN1_H */ -diff --git a/include/linux/asn1_ber_bytecode.h b/include/linux/asn1_ber_bytecode.h -new file mode 100644 -index 0000000..945d44a ---- /dev/null -+++ b/include/linux/asn1_ber_bytecode.h -@@ -0,0 +1,87 @@ -+/* ASN.1 BER/DER/CER parsing state machine internal definitions -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#ifndef _LINUX_ASN1_BER_BYTECODE_H -+#define _LINUX_ASN1_BER_BYTECODE_H -+ -+#ifdef __KERNEL__ -+#include <linux/types.h> -+#endif -+#include <linux/asn1.h> -+ -+typedef int (*asn1_action_t)(void *context, -+ size_t hdrlen, /* In case of ANY type */ -+ unsigned char tag, /* In case of ANY type */ -+ const void *value, size_t vlen); -+ -+struct asn1_decoder { -+ const unsigned char *machine; -+ size_t machlen; -+ const asn1_action_t *actions; -+}; -+ -+enum asn1_opcode { -+ /* The tag-matching ops come first and the odd-numbered slots -+ * are for OR_SKIP ops. -+ */ -+#define ASN1_OP_MATCH__SKIP 0x01 -+#define ASN1_OP_MATCH__ACT 0x02 -+#define ASN1_OP_MATCH__JUMP 0x04 -+#define ASN1_OP_MATCH__ANY 0x08 -+#define ASN1_OP_MATCH__COND 0x10 -+ -+ ASN1_OP_MATCH = 0x00, -+ ASN1_OP_MATCH_OR_SKIP = 0x01, -+ ASN1_OP_MATCH_ACT = 0x02, -+ ASN1_OP_MATCH_ACT_OR_SKIP = 0x03, -+ ASN1_OP_MATCH_JUMP = 0x04, -+ ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05, -+ ASN1_OP_MATCH_ANY = 0x08, -+ ASN1_OP_MATCH_ANY_ACT = 0x0a, -+ /* Everything before here matches unconditionally */ -+ -+ ASN1_OP_COND_MATCH_OR_SKIP = 0x11, -+ ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13, -+ ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15, -+ ASN1_OP_COND_MATCH_ANY = 0x18, -+ ASN1_OP_COND_MATCH_ANY_ACT = 0x1a, -+ -+ /* Everything before here will want a tag from the data */ -+#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT -+ -+ /* These are here to help fill up space */ -+ ASN1_OP_COND_FAIL = 0x1b, -+ ASN1_OP_COMPLETE = 0x1c, -+ ASN1_OP_ACT = 0x1d, -+ ASN1_OP_RETURN = 0x1e, -+ -+ /* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */ -+ ASN1_OP_END_SEQ = 0x20, -+ ASN1_OP_END_SET = 0x21, -+ ASN1_OP_END_SEQ_OF = 0x22, -+ ASN1_OP_END_SET_OF = 0x23, -+ ASN1_OP_END_SEQ_ACT = 0x24, -+ ASN1_OP_END_SET_ACT = 0x25, -+ ASN1_OP_END_SEQ_OF_ACT = 0x26, -+ ASN1_OP_END_SET_OF_ACT = 0x27, -+#define ASN1_OP_END__SET 0x01 -+#define ASN1_OP_END__OF 0x02 -+#define ASN1_OP_END__ACT 0x04 -+ -+ ASN1_OP__NR -+}; -+ -+#define _tag(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | ASN1_##TAG) -+#define _tagn(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | TAG) -+#define _jump_target(N) (N) -+#define _action(N) (N) -+ -+#endif /* _LINUX_ASN1_BER_BYTECODE_H */ -diff --git a/init/Kconfig b/init/Kconfig -index 7452e19..fa8ccad 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1626,4 +1626,12 @@ config PADATA - depends on SMP - bool - -+config ASN1 -+ tristate -+ help -+ Build a simple ASN.1 grammar compiler that produces a bytecode output -+ that can be interpreted by the ASN.1 stream decoder and used to -+ inform it as to what tags are to be expected in a stream and what -+ functions to call on what tags. -+ - source "kernel/Kconfig.locks" -diff --git a/scripts/.gitignore b/scripts/.gitignore -index 65f362d..fb070fa 100644 ---- a/scripts/.gitignore -+++ b/scripts/.gitignore -@@ -10,3 +10,4 @@ ihex2fw - recordmcount - docproc - sortextable -+asn1_compiler -diff --git a/scripts/Makefile b/scripts/Makefile -index a55b006..01e7adb 100644 ---- a/scripts/Makefile -+++ b/scripts/Makefile -@@ -16,8 +16,10 @@ hostprogs-$(CONFIG_VT) += conmakehash - hostprogs-$(CONFIG_IKCONFIG) += bin2c - hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount - hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable -+hostprogs-$(CONFIG_ASN1) += asn1_compiler - - HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include -+HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include - - always := $(hostprogs-y) $(hostprogs-m) - -diff --git a/scripts/Makefile.build b/scripts/Makefile.build -index ff1720d..0e801c3 100644 ---- a/scripts/Makefile.build -+++ b/scripts/Makefile.build -@@ -354,6 +354,17 @@ quiet_cmd_cpp_lds_S = LDS $@ - $(obj)/%.lds: $(src)/%.lds.S FORCE - $(call if_changed_dep,cpp_lds_S) - -+# ASN.1 grammar -+# --------------------------------------------------------------------------- -+quiet_cmd_asn1_compiler = ASN.1 $@ -+ cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \ -+ $(subst .h,.c,$@) $(subst .c,.h,$@) -+ -+.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h -+ -+$(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler -+ $(call cmd,asn1_compiler) -+ - # Build the compiled-in targets - # --------------------------------------------------------------------------- - -diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c -new file mode 100644 -index 0000000..db0e5cd ---- /dev/null -+++ b/scripts/asn1_compiler.c -@@ -0,0 +1,1545 @@ -+/* Simplified ASN.1 notation parser -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#include <stdarg.h> -+#include <stdio.h> -+#include <stdlib.h> -+#include <stdint.h> -+#include <string.h> -+#include <ctype.h> -+#include <unistd.h> -+#include <fcntl.h> -+#include <sys/stat.h> -+#include <linux/asn1_ber_bytecode.h> -+ -+enum token_type { -+ DIRECTIVE_ABSENT, -+ DIRECTIVE_ALL, -+ DIRECTIVE_ANY, -+ DIRECTIVE_APPLICATION, -+ DIRECTIVE_AUTOMATIC, -+ DIRECTIVE_BEGIN, -+ DIRECTIVE_BIT, -+ DIRECTIVE_BMPString, -+ DIRECTIVE_BOOLEAN, -+ DIRECTIVE_BY, -+ DIRECTIVE_CHARACTER, -+ DIRECTIVE_CHOICE, -+ DIRECTIVE_CLASS, -+ DIRECTIVE_COMPONENT, -+ DIRECTIVE_COMPONENTS, -+ DIRECTIVE_CONSTRAINED, -+ DIRECTIVE_CONTAINING, -+ DIRECTIVE_DEFAULT, -+ DIRECTIVE_DEFINED, -+ DIRECTIVE_DEFINITIONS, -+ DIRECTIVE_EMBEDDED, -+ DIRECTIVE_ENCODED, -+ DIRECTIVE_ENCODING_CONTROL, -+ DIRECTIVE_END, -+ DIRECTIVE_ENUMERATED, -+ DIRECTIVE_EXCEPT, -+ DIRECTIVE_EXPLICIT, -+ DIRECTIVE_EXPORTS, -+ DIRECTIVE_EXTENSIBILITY, -+ DIRECTIVE_EXTERNAL, -+ DIRECTIVE_FALSE, -+ DIRECTIVE_FROM, -+ DIRECTIVE_GeneralString, -+ DIRECTIVE_GeneralizedTime, -+ DIRECTIVE_GraphicString, -+ DIRECTIVE_IA5String, -+ DIRECTIVE_IDENTIFIER, -+ DIRECTIVE_IMPLICIT, -+ DIRECTIVE_IMPLIED, -+ DIRECTIVE_IMPORTS, -+ DIRECTIVE_INCLUDES, -+ DIRECTIVE_INSTANCE, -+ DIRECTIVE_INSTRUCTIONS, -+ DIRECTIVE_INTEGER, -+ DIRECTIVE_INTERSECTION, -+ DIRECTIVE_ISO646String, -+ DIRECTIVE_MAX, -+ DIRECTIVE_MIN, -+ DIRECTIVE_MINUS_INFINITY, -+ DIRECTIVE_NULL, -+ DIRECTIVE_NumericString, -+ DIRECTIVE_OBJECT, -+ DIRECTIVE_OCTET, -+ DIRECTIVE_OF, -+ DIRECTIVE_OPTIONAL, -+ DIRECTIVE_ObjectDescriptor, -+ DIRECTIVE_PATTERN, -+ DIRECTIVE_PDV, -+ DIRECTIVE_PLUS_INFINITY, -+ DIRECTIVE_PRESENT, -+ DIRECTIVE_PRIVATE, -+ DIRECTIVE_PrintableString, -+ DIRECTIVE_REAL, -+ DIRECTIVE_RELATIVE_OID, -+ DIRECTIVE_SEQUENCE, -+ DIRECTIVE_SET, -+ DIRECTIVE_SIZE, -+ DIRECTIVE_STRING, -+ DIRECTIVE_SYNTAX, -+ DIRECTIVE_T61String, -+ DIRECTIVE_TAGS, -+ DIRECTIVE_TRUE, -+ DIRECTIVE_TeletexString, -+ DIRECTIVE_UNION, -+ DIRECTIVE_UNIQUE, -+ DIRECTIVE_UNIVERSAL, -+ DIRECTIVE_UTCTime, -+ DIRECTIVE_UTF8String, -+ DIRECTIVE_UniversalString, -+ DIRECTIVE_VideotexString, -+ DIRECTIVE_VisibleString, -+ DIRECTIVE_WITH, -+ NR__DIRECTIVES, -+ TOKEN_ASSIGNMENT = NR__DIRECTIVES, -+ TOKEN_OPEN_CURLY, -+ TOKEN_CLOSE_CURLY, -+ TOKEN_OPEN_SQUARE, -+ TOKEN_CLOSE_SQUARE, -+ TOKEN_OPEN_ACTION, -+ TOKEN_CLOSE_ACTION, -+ TOKEN_COMMA, -+ TOKEN_NUMBER, -+ TOKEN_TYPE_NAME, -+ TOKEN_ELEMENT_NAME, -+ NR__TOKENS -+}; -+ -+static const unsigned char token_to_tag[NR__TOKENS] = { -+ /* EOC goes first */ -+ [DIRECTIVE_BOOLEAN] = ASN1_BOOL, -+ [DIRECTIVE_INTEGER] = ASN1_INT, -+ [DIRECTIVE_BIT] = ASN1_BTS, -+ [DIRECTIVE_OCTET] = ASN1_OTS, -+ [DIRECTIVE_NULL] = ASN1_NULL, -+ [DIRECTIVE_OBJECT] = ASN1_OID, -+ [DIRECTIVE_ObjectDescriptor] = ASN1_ODE, -+ [DIRECTIVE_EXTERNAL] = ASN1_EXT, -+ [DIRECTIVE_REAL] = ASN1_REAL, -+ [DIRECTIVE_ENUMERATED] = ASN1_ENUM, -+ [DIRECTIVE_EMBEDDED] = 0, -+ [DIRECTIVE_UTF8String] = ASN1_UTF8STR, -+ [DIRECTIVE_RELATIVE_OID] = ASN1_RELOID, -+ /* 14 */ -+ /* 15 */ -+ [DIRECTIVE_SEQUENCE] = ASN1_SEQ, -+ [DIRECTIVE_SET] = ASN1_SET, -+ [DIRECTIVE_NumericString] = ASN1_NUMSTR, -+ [DIRECTIVE_PrintableString] = ASN1_PRNSTR, -+ [DIRECTIVE_T61String] = ASN1_TEXSTR, -+ [DIRECTIVE_TeletexString] = ASN1_TEXSTR, -+ [DIRECTIVE_VideotexString] = ASN1_VIDSTR, -+ [DIRECTIVE_IA5String] = ASN1_IA5STR, -+ [DIRECTIVE_UTCTime] = ASN1_UNITIM, -+ [DIRECTIVE_GeneralizedTime] = ASN1_GENTIM, -+ [DIRECTIVE_GraphicString] = ASN1_GRASTR, -+ [DIRECTIVE_VisibleString] = ASN1_VISSTR, -+ [DIRECTIVE_GeneralString] = ASN1_GENSTR, -+ [DIRECTIVE_UniversalString] = ASN1_UNITIM, -+ [DIRECTIVE_CHARACTER] = ASN1_CHRSTR, -+ [DIRECTIVE_BMPString] = ASN1_BMPSTR, -+}; -+ -+static const char asn1_classes[4][5] = { -+ [ASN1_UNIV] = "UNIV", -+ [ASN1_APPL] = "APPL", -+ [ASN1_CONT] = "CONT", -+ [ASN1_PRIV] = "PRIV" -+}; -+ -+static const char asn1_methods[2][5] = { -+ [ASN1_UNIV] = "PRIM", -+ [ASN1_APPL] = "CONS" -+}; -+ -+static const char *const asn1_universal_tags[32] = { -+ "EOC", -+ "BOOL", -+ "INT", -+ "BTS", -+ "OTS", -+ "NULL", -+ "OID", -+ "ODE", -+ "EXT", -+ "REAL", -+ "ENUM", -+ "EPDV", -+ "UTF8STR", -+ "RELOID", -+ NULL, /* 14 */ -+ NULL, /* 15 */ -+ "SEQ", -+ "SET", -+ "NUMSTR", -+ "PRNSTR", -+ "TEXSTR", -+ "VIDSTR", -+ "IA5STR", -+ "UNITIM", -+ "GENTIM", -+ "GRASTR", -+ "VISSTR", -+ "GENSTR", -+ "UNISTR", -+ "CHRSTR", -+ "BMPSTR", -+ NULL /* 31 */ -+}; -+ -+static const char *filename; -+static const char *grammar_name; -+static const char *outputname; -+static const char *headername; -+ -+static const char *const directives[NR__DIRECTIVES] = { -+#define _(X) [DIRECTIVE_##X] = #X -+ _(ABSENT), -+ _(ALL), -+ _(ANY), -+ _(APPLICATION), -+ _(AUTOMATIC), -+ _(BEGIN), -+ _(BIT), -+ _(BMPString), -+ _(BOOLEAN), -+ _(BY), -+ _(CHARACTER), -+ _(CHOICE), -+ _(CLASS), -+ _(COMPONENT), -+ _(COMPONENTS), -+ _(CONSTRAINED), -+ _(CONTAINING), -+ _(DEFAULT), -+ _(DEFINED), -+ _(DEFINITIONS), -+ _(EMBEDDED), -+ _(ENCODED), -+ [DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL", -+ _(END), -+ _(ENUMERATED), -+ _(EXCEPT), -+ _(EXPLICIT), -+ _(EXPORTS), -+ _(EXTENSIBILITY), -+ _(EXTERNAL), -+ _(FALSE), -+ _(FROM), -+ _(GeneralString), -+ _(GeneralizedTime), -+ _(GraphicString), -+ _(IA5String), -+ _(IDENTIFIER), -+ _(IMPLICIT), -+ _(IMPLIED), -+ _(IMPORTS), -+ _(INCLUDES), -+ _(INSTANCE), -+ _(INSTRUCTIONS), -+ _(INTEGER), -+ _(INTERSECTION), -+ _(ISO646String), -+ _(MAX), -+ _(MIN), -+ [DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY", -+ [DIRECTIVE_NULL] = "NULL", -+ _(NumericString), -+ _(OBJECT), -+ _(OCTET), -+ _(OF), -+ _(OPTIONAL), -+ _(ObjectDescriptor), -+ _(PATTERN), -+ _(PDV), -+ [DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY", -+ _(PRESENT), -+ _(PRIVATE), -+ _(PrintableString), -+ _(REAL), -+ [DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID", -+ _(SEQUENCE), -+ _(SET), -+ _(SIZE), -+ _(STRING), -+ _(SYNTAX), -+ _(T61String), -+ _(TAGS), -+ _(TRUE), -+ _(TeletexString), -+ _(UNION), -+ _(UNIQUE), -+ _(UNIVERSAL), -+ _(UTCTime), -+ _(UTF8String), -+ _(UniversalString), -+ _(VideotexString), -+ _(VisibleString), -+ _(WITH) -+}; -+ -+struct action { -+ struct action *next; -+ unsigned char index; -+ char name[]; -+}; -+ -+static struct action *action_list; -+static unsigned nr_actions; -+ -+struct token { -+ unsigned short line; -+ enum token_type token_type : 8; -+ unsigned char size; -+ struct action *action; -+ const char *value; -+ struct type *type; -+}; -+ -+static struct token *token_list; -+static unsigned nr_tokens; -+ -+static int directive_compare(const void *_key, const void *_pdir) -+{ -+ const struct token *token = _key; -+ const char *const *pdir = _pdir, *dir = *pdir; -+ size_t dlen, clen; -+ int val; -+ -+ dlen = strlen(dir); -+ clen = (dlen < token->size) ? dlen : token->size; -+ -+ //printf("cmp(%*.*s,%s) = ", -+ // (int)token->size, (int)token->size, token->value, -+ // dir); -+ -+ val = memcmp(token->value, dir, clen); -+ if (val != 0) { -+ //printf("%d [cmp]\n", val); -+ return val; -+ } -+ -+ if (dlen == token->size) { -+ //printf("0\n"); -+ return 0; -+ } -+ //printf("%d\n", (int)dlen - (int)token->size); -+ return dlen - token->size; /* shorter -> negative */ -+} -+ -+/* -+ * Tokenise an ASN.1 grammar -+ */ -+static void tokenise(char *buffer, char *end) -+{ -+ struct token *tokens; -+ char *line, *nl, *p, *q; -+ unsigned tix, lineno; -+ -+ /* Assume we're going to have half as many tokens as we have -+ * characters -+ */ -+ token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token)); -+ if (!tokens) { -+ perror(NULL); -+ exit(1); -+ } -+ tix = 0; -+ -+ lineno = 0; -+ while (buffer < end) { -+ /* First of all, break out a line */ -+ lineno++; -+ line = buffer; -+ nl = memchr(line, '\n', end - buffer); -+ if (!nl) { -+ buffer = nl = end; -+ } else { -+ buffer = nl + 1; -+ *nl = '\0'; -+ } -+ -+ /* Remove "--" comments */ -+ p = line; -+ next_comment: -+ while ((p = memchr(p, '-', nl - p))) { -+ if (p[1] == '-') { -+ /* Found a comment; see if there's a terminator */ -+ q = p + 2; -+ while ((q = memchr(q, '-', nl - q))) { -+ if (q[1] == '-') { -+ /* There is - excise the comment */ -+ q += 2; -+ memmove(p, q, nl - q); -+ goto next_comment; -+ } -+ q++; -+ } -+ *p = '\0'; -+ nl = p; -+ break; -+ } else { -+ p++; -+ } -+ } -+ -+ p = line; -+ while (p < nl) { -+ /* Skip white space */ -+ while (p < nl && isspace(*p)) -+ *(p++) = 0; -+ if (p >= nl) -+ break; -+ -+ tokens[tix].line = lineno; -+ tokens[tix].value = p; -+ -+ /* Handle string tokens */ -+ if (isalpha(*p)) { -+ const char **dir; -+ -+ /* Can be a directive, type name or element -+ * name. Find the end of the name. -+ */ -+ q = p + 1; -+ while (q < nl && (isalnum(*q) || *q == '-' || *q == '_')) -+ q++; -+ tokens[tix].size = q - p; -+ p = q; -+ -+ /* If it begins with a lowercase letter then -+ * it's an element name -+ */ -+ if (islower(tokens[tix].value[0])) { -+ tokens[tix++].token_type = TOKEN_ELEMENT_NAME; -+ continue; -+ } -+ -+ /* Otherwise we need to search the directive -+ * table -+ */ -+ dir = bsearch(&tokens[tix], directives, -+ sizeof(directives) / sizeof(directives[1]), -+ sizeof(directives[1]), -+ directive_compare); -+ if (dir) { -+ tokens[tix++].token_type = dir - directives; -+ continue; -+ } -+ -+ tokens[tix++].token_type = TOKEN_TYPE_NAME; -+ continue; -+ } -+ -+ /* Handle numbers */ -+ if (isdigit(*p)) { -+ /* Find the end of the number */ -+ q = p + 1; -+ while (q < nl && (isdigit(*q))) -+ q++; -+ tokens[tix].size = q - p; -+ p = q; -+ tokens[tix++].token_type = TOKEN_NUMBER; -+ continue; -+ } -+ -+ if (nl - p >= 3) { -+ if (memcmp(p, "::=", 3) == 0) { -+ p += 3; -+ tokens[tix].size = 3; -+ tokens[tix++].token_type = TOKEN_ASSIGNMENT; -+ continue; -+ } -+ } -+ -+ if (nl - p >= 2) { -+ if (memcmp(p, "({", 2) == 0) { -+ p += 2; -+ tokens[tix].size = 2; -+ tokens[tix++].token_type = TOKEN_OPEN_ACTION; -+ continue; -+ } -+ if (memcmp(p, "})", 2) == 0) { -+ p += 2; -+ tokens[tix].size = 2; -+ tokens[tix++].token_type = TOKEN_CLOSE_ACTION; -+ continue; -+ } -+ } -+ -+ if (nl - p >= 1) { -+ tokens[tix].size = 1; -+ switch (*p) { -+ case '{': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_OPEN_CURLY; -+ continue; -+ case '}': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_CLOSE_CURLY; -+ continue; -+ case '[': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_OPEN_SQUARE; -+ continue; -+ case ']': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_CLOSE_SQUARE; -+ continue; -+ case ',': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_COMMA; -+ continue; -+ default: -+ break; -+ } -+ } -+ -+ fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n", -+ filename, lineno, *p); -+ exit(1); -+ } -+ } -+ -+ nr_tokens = tix; -+ printf("Extracted %u tokens\n", nr_tokens); -+ -+#if 0 -+ { -+ int n; -+ for (n = 0; n < nr_tokens; n++) -+ printf("Token %3u: '%*.*s'\n", -+ n, -+ (int)token_list[n].size, (int)token_list[n].size, -+ token_list[n].value); -+ } -+#endif -+} -+ -+static void build_type_list(void); -+static void parse(void); -+static void render(FILE *out, FILE *hdr); -+ -+/* -+ * -+ */ -+int main(int argc, char **argv) -+{ -+ struct stat st; -+ ssize_t readlen; -+ FILE *out, *hdr; -+ char *buffer, *p; -+ int fd; -+ -+ if (argc != 4) { -+ fprintf(stderr, "Format: %s <grammar-file> <c-file> <hdr-file>\n", -+ argv[0]); -+ exit(2); -+ } -+ -+ filename = argv[1]; -+ outputname = argv[2]; -+ headername = argv[3]; -+ -+ fd = open(filename, O_RDONLY); -+ if (fd < 0) { -+ perror(filename); -+ exit(1); -+ } -+ -+ if (fstat(fd, &st) < 0) { -+ perror(filename); -+ exit(1); -+ } -+ -+ if (!(buffer = malloc(st.st_size + 1))) { -+ perror(NULL); -+ exit(1); -+ } -+ -+ if ((readlen = read(fd, buffer, st.st_size)) < 0) { -+ perror(filename); -+ exit(1); -+ } -+ -+ if (close(fd) < 0) { -+ perror(filename); -+ exit(1); -+ } -+ -+ if (readlen != st.st_size) { -+ fprintf(stderr, "%s: Short read\n", filename); -+ exit(1); -+ } -+ -+ p = strrchr(argv[1], '/'); -+ p = p ? p + 1 : argv[1]; -+ grammar_name = strdup(p); -+ if (!p) { -+ perror(NULL); -+ exit(1); -+ } -+ p = strchr(grammar_name, '.'); -+ if (p) -+ *p = '\0'; -+ -+ buffer[readlen] = 0; -+ tokenise(buffer, buffer + readlen); -+ build_type_list(); -+ parse(); -+ -+ out = fopen(outputname, "w"); -+ if (!out) { -+ perror(outputname); -+ exit(1); -+ } -+ -+ hdr = fopen(headername, "w"); -+ if (!out) { -+ perror(headername); -+ exit(1); -+ } -+ -+ render(out, hdr); -+ -+ if (fclose(out) < 0) { -+ perror(outputname); -+ exit(1); -+ } -+ -+ if (fclose(hdr) < 0) { -+ perror(headername); -+ exit(1); -+ } -+ -+ return 0; -+} -+ -+enum compound { -+ NOT_COMPOUND, -+ SET, -+ SET_OF, -+ SEQUENCE, -+ SEQUENCE_OF, -+ CHOICE, -+ ANY, -+ TYPE_REF, -+ TAG_OVERRIDE -+}; -+ -+struct element { -+ struct type *type_def; -+ struct token *name; -+ struct token *type; -+ struct action *action; -+ struct element *children; -+ struct element *next; -+ struct element *render_next; -+ struct element *list_next; -+ uint8_t n_elements; -+ enum compound compound : 8; -+ enum asn1_class class : 8; -+ enum asn1_method method : 8; -+ uint8_t tag; -+ unsigned entry_index; -+ unsigned flags; -+#define ELEMENT_IMPLICIT 0x0001 -+#define ELEMENT_EXPLICIT 0x0002 -+#define ELEMENT_MARKED 0x0004 -+#define ELEMENT_RENDERED 0x0008 -+#define ELEMENT_SKIPPABLE 0x0010 -+#define ELEMENT_CONDITIONAL 0x0020 -+}; -+ -+struct type { -+ struct token *name; -+ struct token *def; -+ struct element *element; -+ unsigned ref_count; -+ unsigned flags; -+#define TYPE_STOP_MARKER 0x0001 -+#define TYPE_BEGIN 0x0002 -+}; -+ -+static struct type *type_list; -+static struct type **type_index; -+static unsigned nr_types; -+ -+static int type_index_compare(const void *_a, const void *_b) -+{ -+ const struct type *const *a = _a, *const *b = _b; -+ -+ if ((*a)->name->size != (*b)->name->size) -+ return (*a)->name->size - (*b)->name->size; -+ else -+ return memcmp((*a)->name->value, (*b)->name->value, -+ (*a)->name->size); -+} -+ -+static int type_finder(const void *_key, const void *_ti) -+{ -+ const struct token *token = _key; -+ const struct type *const *ti = _ti; -+ const struct type *type = *ti; -+ -+ if (token->size != type->name->size) -+ return token->size - type->name->size; -+ else -+ return memcmp(token->value, type->name->value, -+ token->size); -+} -+ -+/* -+ * Build up a list of types and a sorted index to that list. -+ */ -+static void build_type_list(void) -+{ -+ struct type *types; -+ unsigned nr, t, n; -+ -+ nr = 0; -+ for (n = 0; n < nr_tokens - 1; n++) -+ if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && -+ token_list[n + 1].token_type == TOKEN_ASSIGNMENT) -+ nr++; -+ -+ if (nr == 0) { -+ fprintf(stderr, "%s: No defined types\n", filename); -+ exit(1); -+ } -+ -+ nr_types = nr; -+ types = type_list = calloc(nr + 1, sizeof(type_list[0])); -+ if (!type_list) { -+ perror(NULL); -+ exit(1); -+ } -+ type_index = calloc(nr, sizeof(type_index[0])); -+ if (!type_index) { -+ perror(NULL); -+ exit(1); -+ } -+ -+ t = 0; -+ types[t].flags |= TYPE_BEGIN; -+ for (n = 0; n < nr_tokens - 1; n++) { -+ if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && -+ token_list[n + 1].token_type == TOKEN_ASSIGNMENT) { -+ types[t].name = &token_list[n]; -+ type_index[t] = &types[t]; -+ t++; -+ } -+ } -+ types[t].name = &token_list[n + 1]; -+ types[t].flags |= TYPE_STOP_MARKER; -+ -+ qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); -+ -+ printf("Extracted %u types\n", nr_types); -+#if 0 -+ for (n = 0; n < nr_types; n++) { -+ struct type *type = type_index[n]; -+ printf("- %*.*s\n", -+ (int)type->name->size, -+ (int)type->name->size, -+ type->name->value); -+ } -+#endif -+} -+ -+static struct element *parse_type(struct token **_cursor, struct token *stop, -+ struct token *name); -+ -+/* -+ * Parse the token stream -+ */ -+static void parse(void) -+{ -+ struct token *cursor; -+ struct type *type; -+ -+ /* Parse one type definition statement at a time */ -+ type = type_list; -+ do { -+ cursor = type->name; -+ -+ if (cursor[0].token_type != TOKEN_TYPE_NAME || -+ cursor[1].token_type != TOKEN_ASSIGNMENT) -+ abort(); -+ cursor += 2; -+ -+ type->element = parse_type(&cursor, type[1].name, NULL); -+ type->element->type_def = type; -+ -+ if (cursor != type[1].name) { -+ fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ } while (type++, !(type->flags & TYPE_STOP_MARKER)); -+ -+ printf("Extracted %u actions\n", nr_actions); -+} -+ -+static struct element *element_list; -+ -+static struct element *alloc_elem(struct token *type) -+{ -+ struct element *e = calloc(1, sizeof(*e)); -+ if (!e) { -+ perror(NULL); -+ exit(1); -+ } -+ e->list_next = element_list; -+ element_list = e; -+ return e; -+} -+ -+static struct element *parse_compound(struct token **_cursor, struct token *end, -+ int alternates); -+ -+/* -+ * Parse one type definition statement -+ */ -+static struct element *parse_type(struct token **_cursor, struct token *end, -+ struct token *name) -+{ -+ struct element *top, *element; -+ struct action *action, **ppaction; -+ struct token *cursor = *_cursor; -+ struct type **ref; -+ char *p; -+ int labelled = 0, implicit = 0; -+ -+ top = element = alloc_elem(cursor); -+ element->class = ASN1_UNIV; -+ element->method = ASN1_PRIM; -+ element->tag = token_to_tag[cursor->token_type]; -+ element->name = name; -+ -+ /* Extract the tag value if one given */ -+ if (cursor->token_type == TOKEN_OPEN_SQUARE) { -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ switch (cursor->token_type) { -+ case DIRECTIVE_UNIVERSAL: -+ element->class = ASN1_UNIV; -+ cursor++; -+ break; -+ case DIRECTIVE_APPLICATION: -+ element->class = ASN1_APPL; -+ cursor++; -+ break; -+ case TOKEN_NUMBER: -+ element->class = ASN1_CONT; -+ break; -+ case DIRECTIVE_PRIVATE: -+ element->class = ASN1_PRIV; -+ cursor++; -+ break; -+ default: -+ fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_NUMBER) { -+ fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ element->tag &= ~0x1f; -+ element->tag |= strtoul(cursor->value, &p, 10); -+ if (p - cursor->value != cursor->size) -+ abort(); -+ cursor++; -+ -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_CLOSE_SQUARE) { -+ fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ labelled = 1; -+ } -+ -+ /* Handle implicit and explicit markers */ -+ if (cursor->token_type == DIRECTIVE_IMPLICIT) { -+ element->flags |= ELEMENT_IMPLICIT; -+ implicit = 1; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ } else if (cursor->token_type == DIRECTIVE_EXPLICIT) { -+ element->flags |= ELEMENT_EXPLICIT; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ } -+ -+ if (labelled) { -+ if (!implicit) -+ element->method |= ASN1_CONS; -+ element->compound = implicit ? TAG_OVERRIDE : SEQUENCE; -+ element->children = alloc_elem(cursor); -+ element = element->children; -+ element->class = ASN1_UNIV; -+ element->method = ASN1_PRIM; -+ element->tag = token_to_tag[cursor->token_type]; -+ element->name = name; -+ } -+ -+ /* Extract the type we're expecting here */ -+ element->type = cursor; -+ switch (cursor->token_type) { -+ case DIRECTIVE_ANY: -+ element->compound = ANY; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_NULL: -+ case DIRECTIVE_BOOLEAN: -+ case DIRECTIVE_ENUMERATED: -+ case DIRECTIVE_INTEGER: -+ element->compound = NOT_COMPOUND; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_EXTERNAL: -+ element->method = ASN1_CONS; -+ -+ case DIRECTIVE_BMPString: -+ case DIRECTIVE_GeneralString: -+ case DIRECTIVE_GraphicString: -+ case DIRECTIVE_IA5String: -+ case DIRECTIVE_ISO646String: -+ case DIRECTIVE_NumericString: -+ case DIRECTIVE_PrintableString: -+ case DIRECTIVE_T61String: -+ case DIRECTIVE_TeletexString: -+ case DIRECTIVE_UniversalString: -+ case DIRECTIVE_UTF8String: -+ case DIRECTIVE_VideotexString: -+ case DIRECTIVE_VisibleString: -+ case DIRECTIVE_ObjectDescriptor: -+ case DIRECTIVE_GeneralizedTime: -+ case DIRECTIVE_UTCTime: -+ element->compound = NOT_COMPOUND; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_BIT: -+ case DIRECTIVE_OCTET: -+ element->compound = NOT_COMPOUND; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != DIRECTIVE_STRING) -+ goto parse_error; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_OBJECT: -+ element->compound = NOT_COMPOUND; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != DIRECTIVE_IDENTIFIER) -+ goto parse_error; -+ cursor++; -+ break; -+ -+ case TOKEN_TYPE_NAME: -+ element->compound = TYPE_REF; -+ ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]), -+ type_finder); -+ if (!ref) { -+ fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor->type = *ref; -+ (*ref)->ref_count++; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_CHOICE: -+ element->compound = CHOICE; -+ cursor++; -+ element->children = parse_compound(&cursor, end, 1); -+ break; -+ -+ case DIRECTIVE_SEQUENCE: -+ element->compound = SEQUENCE; -+ element->method = ASN1_CONS; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type == DIRECTIVE_OF) { -+ element->compound = SEQUENCE_OF; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ element->children = parse_type(&cursor, end, NULL); -+ } else { -+ element->children = parse_compound(&cursor, end, 0); -+ } -+ break; -+ -+ case DIRECTIVE_SET: -+ element->compound = SET; -+ element->method = ASN1_CONS; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type == DIRECTIVE_OF) { -+ element->compound = SET_OF; -+ cursor++; -+ if (cursor >= end) -+ goto parse_error; -+ element->children = parse_type(&cursor, end, NULL); -+ } else { -+ element->children = parse_compound(&cursor, end, 1); -+ } -+ break; -+ -+ default: -+ fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ /* Handle elements that are optional */ -+ if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL || -+ cursor->token_type == DIRECTIVE_DEFAULT) -+ ) { -+ cursor++; -+ top->flags |= ELEMENT_SKIPPABLE; -+ } -+ -+ if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) { -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_ELEMENT_NAME) { -+ fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ action = malloc(sizeof(struct action) + cursor->size + 1); -+ if (!action) { -+ perror(NULL); -+ exit(1); -+ } -+ action->index = 0; -+ memcpy(action->name, cursor->value, cursor->size); -+ action->name[cursor->size] = 0; -+ -+ for (ppaction = &action_list; -+ *ppaction; -+ ppaction = &(*ppaction)->next -+ ) { -+ int cmp = strcmp(action->name, (*ppaction)->name); -+ if (cmp == 0) { -+ free(action); -+ action = *ppaction; -+ goto found; -+ } -+ if (cmp < 0) { -+ action->next = *ppaction; -+ *ppaction = action; -+ nr_actions++; -+ goto found; -+ } -+ } -+ action->next = NULL; -+ *ppaction = action; -+ nr_actions++; -+ found: -+ -+ element->action = action; -+ cursor->action = action; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_CLOSE_ACTION) { -+ fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor++; -+ } -+ -+ *_cursor = cursor; -+ return top; -+ -+parse_error: -+ fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ -+overrun_error: -+ fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); -+ exit(1); -+} -+ -+/* -+ * Parse a compound type list -+ */ -+static struct element *parse_compound(struct token **_cursor, struct token *end, -+ int alternates) -+{ -+ struct element *children, **child_p = &children, *element; -+ struct token *cursor = *_cursor, *name; -+ -+ if (cursor->token_type != TOKEN_OPEN_CURLY) { -+ fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ -+ if (cursor->token_type == TOKEN_OPEN_CURLY) { -+ fprintf(stderr, "%s:%d: Empty compound\n", -+ filename, cursor->line); -+ exit(1); -+ } -+ -+ for (;;) { -+ name = NULL; -+ if (cursor->token_type == TOKEN_ELEMENT_NAME) { -+ name = cursor; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ } -+ -+ element = parse_type(&cursor, end, name); -+ if (alternates) -+ element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL; -+ -+ *child_p = element; -+ child_p = &element->next; -+ -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_COMMA) -+ break; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ } -+ -+ children->flags &= ~ELEMENT_CONDITIONAL; -+ -+ if (cursor->token_type != TOKEN_CLOSE_CURLY) { -+ fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor++; -+ -+ *_cursor = cursor; -+ return children; -+ -+overrun_error: -+ fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); -+ exit(1); -+} -+ -+static void render_element(FILE *out, struct element *e, struct element *tag); -+static void render_out_of_line_list(FILE *out); -+ -+static int nr_entries; -+static int render_depth = 1; -+static struct element *render_list, **render_list_p = &render_list; -+ -+__attribute__((format(printf, 2, 3))) -+static void render_opcode(FILE *out, const char *fmt, ...) -+{ -+ va_list va; -+ -+ if (out) { -+ fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, ""); -+ va_start(va, fmt); -+ vfprintf(out, fmt, va); -+ va_end(va); -+ } -+ nr_entries++; -+} -+ -+__attribute__((format(printf, 2, 3))) -+static void render_more(FILE *out, const char *fmt, ...) -+{ -+ va_list va; -+ -+ if (out) { -+ va_start(va, fmt); -+ vfprintf(out, fmt, va); -+ va_end(va); -+ } -+} -+ -+/* -+ * Render the grammar into a state machine definition. -+ */ -+static void render(FILE *out, FILE *hdr) -+{ -+ struct element *e; -+ struct action *action; -+ struct type *root; -+ int index; -+ -+ fprintf(hdr, "/*\n"); -+ fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n"); -+ fprintf(hdr, " *\n"); -+ fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name); -+ fprintf(hdr, " */\n"); -+ fprintf(hdr, "#include <linux/asn1_decoder.h>\n"); -+ fprintf(hdr, "\n"); -+ fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name); -+ if (ferror(hdr)) { -+ perror(headername); -+ exit(1); -+ } -+ -+ fprintf(out, "/*\n"); -+ fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n"); -+ fprintf(out, " *\n"); -+ fprintf(out, " * ASN.1 parser for %s\n", grammar_name); -+ fprintf(out, " */\n"); -+ fprintf(out, "#include <linux/asn1_ber_bytecode.h>\n"); -+ fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name); -+ fprintf(out, "\n"); -+ if (ferror(out)) { -+ perror(outputname); -+ exit(1); -+ } -+ -+ /* Tabulate the action functions we might have to call */ -+ fprintf(hdr, "\n"); -+ index = 0; -+ for (action = action_list; action; action = action->next) { -+ action->index = index++; -+ fprintf(hdr, -+ "extern int %s(void *, size_t, unsigned char," -+ " const void *, size_t);\n", -+ action->name); -+ } -+ fprintf(hdr, "\n"); -+ -+ fprintf(out, "enum %s_actions {\n", grammar_name); -+ for (action = action_list; action; action = action->next) -+ fprintf(out, "\tACT_%s = %u,\n", -+ action->name, action->index); -+ fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions); -+ fprintf(out, "};\n"); -+ -+ fprintf(out, "\n"); -+ fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n", -+ grammar_name, grammar_name); -+ for (action = action_list; action; action = action->next) -+ fprintf(out, "\t[%4u] = %s,\n", action->index, action->name); -+ fprintf(out, "};\n"); -+ -+ if (ferror(out)) { -+ perror(outputname); -+ exit(1); -+ } -+ -+ /* We do two passes - the first one calculates all the offsets */ -+ printf("Pass 1\n"); -+ nr_entries = 0; -+ root = &type_list[0]; -+ render_element(NULL, root->element, NULL); -+ render_opcode(NULL, "ASN1_OP_COMPLETE,\n"); -+ render_out_of_line_list(NULL); -+ -+ for (e = element_list; e; e = e->list_next) -+ e->flags &= ~ELEMENT_RENDERED; -+ -+ /* And then we actually render */ -+ printf("Pass 2\n"); -+ fprintf(out, "\n"); -+ fprintf(out, "static const unsigned char %s_machine[] = {\n", -+ grammar_name); -+ -+ nr_entries = 0; -+ root = &type_list[0]; -+ render_element(out, root->element, NULL); -+ render_opcode(out, "ASN1_OP_COMPLETE,\n"); -+ render_out_of_line_list(out); -+ -+ fprintf(out, "};\n"); -+ -+ fprintf(out, "\n"); -+ fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name); -+ fprintf(out, "\t.machine = %s_machine,\n", grammar_name); -+ fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name); -+ fprintf(out, "\t.actions = %s_action_table,\n", grammar_name); -+ fprintf(out, "};\n"); -+} -+ -+/* -+ * Render the out-of-line elements -+ */ -+static void render_out_of_line_list(FILE *out) -+{ -+ struct element *e, *ce; -+ const char *act; -+ int entry; -+ -+ while ((e = render_list)) { -+ render_list = e->render_next; -+ if (!render_list) -+ render_list_p = &render_list; -+ -+ render_more(out, "\n"); -+ e->entry_index = entry = nr_entries; -+ render_depth++; -+ for (ce = e->children; ce; ce = ce->next) -+ render_element(out, ce, NULL); -+ render_depth--; -+ -+ act = e->action ? "_ACT" : ""; -+ switch (e->compound) { -+ case SEQUENCE: -+ render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); -+ break; -+ case SEQUENCE_OF: -+ render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); -+ render_opcode(out, "_jump_target(%u),\n", entry); -+ break; -+ case SET: -+ render_opcode(out, "ASN1_OP_END_SET%s,\n", act); -+ break; -+ case SET_OF: -+ render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); -+ render_opcode(out, "_jump_target(%u),\n", entry); -+ break; -+ } -+ if (e->action) -+ render_opcode(out, "_action(ACT_%s),\n", -+ e->action->name); -+ render_opcode(out, "ASN1_OP_RETURN,\n"); -+ } -+} -+ -+/* -+ * Render an element. -+ */ -+static void render_element(FILE *out, struct element *e, struct element *tag) -+{ -+ struct element *ec; -+ const char *cond, *act; -+ int entry, skippable = 0, outofline = 0; -+ -+ if (e->flags & ELEMENT_SKIPPABLE || -+ (tag && tag->flags & ELEMENT_SKIPPABLE)) -+ skippable = 1; -+ -+ if ((e->type_def && e->type_def->ref_count > 1) || -+ skippable) -+ outofline = 1; -+ -+ if (e->type_def && out) { -+ render_more(out, "\t// %*.*s\n", -+ (int)e->type_def->name->size, (int)e->type_def->name->size, -+ e->type_def->name->value); -+ } -+ -+ /* Render the operation */ -+ cond = (e->flags & ELEMENT_CONDITIONAL || -+ (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : ""; -+ act = e->action ? "_ACT" : ""; -+ switch (e->compound) { -+ case ANY: -+ render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act); -+ if (e->name) -+ render_more(out, "\t\t// %*.*s", -+ (int)e->name->size, (int)e->name->size, -+ e->name->value); -+ render_more(out, "\n"); -+ goto dont_render_tag; -+ -+ case TAG_OVERRIDE: -+ render_element(out, e->children, e); -+ return; -+ -+ case SEQUENCE: -+ case SEQUENCE_OF: -+ case SET: -+ case SET_OF: -+ render_opcode(out, "ASN1_OP_%sMATCH%s%s,", -+ cond, -+ outofline ? "_JUMP" : "", -+ skippable ? "_OR_SKIP" : ""); -+ break; -+ -+ case CHOICE: -+ goto dont_render_tag; -+ -+ case TYPE_REF: -+ if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0) -+ goto dont_render_tag; -+ default: -+ render_opcode(out, "ASN1_OP_%sMATCH%s%s,", -+ cond, act, -+ skippable ? "_OR_SKIP" : ""); -+ break; -+ } -+ -+ if (e->name) -+ render_more(out, "\t\t// %*.*s", -+ (int)e->name->size, (int)e->name->size, -+ e->name->value); -+ render_more(out, "\n"); -+ -+ /* Render the tag */ -+ if (!tag) -+ tag = e; -+ if (tag->class == ASN1_UNIV && -+ tag->tag != 14 && -+ tag->tag != 15 && -+ tag->tag != 31) -+ render_opcode(out, "_tag(%s, %s, %s),\n", -+ asn1_classes[tag->class], -+ asn1_methods[tag->method | e->method], -+ asn1_universal_tags[tag->tag]); -+ else -+ render_opcode(out, "_tagn(%s, %s, %2u),\n", -+ asn1_classes[tag->class], -+ asn1_methods[tag->method | e->method], -+ tag->tag); -+ tag = NULL; -+dont_render_tag: -+ -+ /* Deal with compound types */ -+ switch (e->compound) { -+ case TYPE_REF: -+ render_element(out, e->type->type->element, tag); -+ if (e->action) -+ render_opcode(out, "ASN1_OP_ACT,\n"); -+ break; -+ -+ case SEQUENCE: -+ if (outofline) { -+ /* Render out-of-line for multiple use or -+ * skipability */ -+ render_opcode(out, "_jump_target(%u),", e->entry_index); -+ if (e->type_def && e->type_def->name) -+ render_more(out, "\t\t// --> %*.*s", -+ (int)e->type_def->name->size, -+ (int)e->type_def->name->size, -+ e->type_def->name->value); -+ render_more(out, "\n"); -+ if (!(e->flags & ELEMENT_RENDERED)) { -+ e->flags |= ELEMENT_RENDERED; -+ *render_list_p = e; -+ render_list_p = &e->render_next; -+ } -+ return; -+ } else { -+ /* Render inline for single use */ -+ render_depth++; -+ for (ec = e->children; ec; ec = ec->next) -+ render_element(out, ec, NULL); -+ render_depth--; -+ render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); -+ } -+ break; -+ -+ case SEQUENCE_OF: -+ case SET_OF: -+ if (outofline) { -+ /* Render out-of-line for multiple use or -+ * skipability */ -+ render_opcode(out, "_jump_target(%u),", e->entry_index); -+ if (e->type_def && e->type_def->name) -+ render_more(out, "\t\t// --> %*.*s", -+ (int)e->type_def->name->size, -+ (int)e->type_def->name->size, -+ e->type_def->name->value); -+ render_more(out, "\n"); -+ if (!(e->flags & ELEMENT_RENDERED)) { -+ e->flags |= ELEMENT_RENDERED; -+ *render_list_p = e; -+ render_list_p = &e->render_next; -+ } -+ return; -+ } else { -+ /* Render inline for single use */ -+ entry = nr_entries; -+ render_depth++; -+ render_element(out, e->children, NULL); -+ render_depth--; -+ if (e->compound == SEQUENCE_OF) -+ render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); -+ else -+ render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); -+ render_opcode(out, "_jump_target(%u),\n", entry); -+ } -+ break; -+ -+ case SET: -+ /* I can't think of a nice way to do SET support without having -+ * a stack of bitmasks to make sure no element is repeated. -+ * The bitmask has also to be checked that no non-optional -+ * elements are left out whilst not preventing optional -+ * elements from being left out. -+ */ -+ fprintf(stderr, "The ASN.1 SET type is not currently supported.\n"); -+ exit(1); -+ -+ case CHOICE: -+ for (ec = e->children; ec; ec = ec->next) -+ render_element(out, ec, NULL); -+ if (!skippable) -+ render_opcode(out, "ASN1_OP_COND_FAIL,\n"); -+ if (e->action) -+ render_opcode(out, "ASN1_OP_ACT,\n"); -+ break; -+ -+ default: -+ break; -+ } -+ -+ if (e->action) -+ render_opcode(out, "_action(ACT_%s),\n", e->action->name); -+} --- -1.7.12.1 - - -From 650c728e4b8d58d72b19973e97c3c765178e81b8 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Mon, 24 Sep 2012 17:11:16 +0100 -Subject: [PATCH 15/37] X.509: Add an ASN.1 decoder - -Add an ASN.1 BER/DER/CER decoder. This uses the bytecode from the ASN.1 -compiler in the previous patch to inform it as to what to expect to find in the -encoded byte stream. The output from the compiler also tells it what functions -to call on what tags, thus allowing the caller to retrieve information. - -The decoder is called as follows: - - int asn1_decoder(const struct asn1_decoder *decoder, - void *context, - const unsigned char *data, - size_t datalen); - -The decoder argument points to the bytecode from the ASN.1 compiler. context -is the caller's context and is passed to the action functions. data and -datalen define the byte stream to be decoded. - -Note that the decoder is currently limited to datalen being less than 64K. -This reduces the amount of stack space used by the decoder because ASN.1 is a -nested construct. Similarly, the decoder is limited to a maximum of 10 levels -of constructed data outside of a leaf node also in an effort to keep stack -usage down. - -These restrictions can be raised if necessary. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - include/linux/asn1_decoder.h | 24 +++ - lib/Makefile | 2 + - lib/asn1_decoder.c | 477 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 503 insertions(+) - create mode 100644 include/linux/asn1_decoder.h - create mode 100644 lib/asn1_decoder.c - -diff --git a/include/linux/asn1_decoder.h b/include/linux/asn1_decoder.h -new file mode 100644 -index 0000000..fa2ff5b ---- /dev/null -+++ b/include/linux/asn1_decoder.h -@@ -0,0 +1,24 @@ -+/* ASN.1 decoder -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#ifndef _LINUX_ASN1_DECODER_H -+#define _LINUX_ASN1_DECODER_H -+ -+#include <linux/asn1.h> -+ -+struct asn1_decoder; -+ -+extern int asn1_ber_decoder(const struct asn1_decoder *decoder, -+ void *context, -+ const unsigned char *data, -+ size_t datalen); -+ -+#endif /* _LINUX_ASN1_DECODER_H */ -diff --git a/lib/Makefile b/lib/Makefile -index b042896..ca856b6 100644 ---- a/lib/Makefile -+++ b/lib/Makefile -@@ -140,6 +140,8 @@ $(foreach file, $(libfdt_files), \ - $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) - lib-$(CONFIG_LIBFDT) += $(libfdt_files) - -+obj-$(CONFIG_ASN1) += asn1_decoder.o -+ - hostprogs-y := gen_crc32table - clean-files := crc32table.h - -diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c -new file mode 100644 -index 0000000..2e4196d ---- /dev/null -+++ b/lib/asn1_decoder.c -@@ -0,0 +1,477 @@ -+/* Decoder for ASN.1 BER/DER/CER encoded bytestream -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#include <linux/export.h> -+#include <linux/kernel.h> -+#include <linux/errno.h> -+#include <linux/asn1_decoder.h> -+#include <linux/asn1_ber_bytecode.h> -+ -+static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { -+ /* OPC TAG JMP ACT */ -+ [ASN1_OP_MATCH] = 1 + 1, -+ [ASN1_OP_MATCH_OR_SKIP] = 1 + 1, -+ [ASN1_OP_MATCH_ACT] = 1 + 1 + 1, -+ [ASN1_OP_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, -+ [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, -+ [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, -+ [ASN1_OP_MATCH_ANY] = 1, -+ [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, -+ [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, -+ [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, -+ [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, -+ [ASN1_OP_COND_MATCH_ANY] = 1, -+ [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, -+ [ASN1_OP_COND_FAIL] = 1, -+ [ASN1_OP_COMPLETE] = 1, -+ [ASN1_OP_ACT] = 1 + 1, -+ [ASN1_OP_RETURN] = 1, -+ [ASN1_OP_END_SEQ] = 1, -+ [ASN1_OP_END_SEQ_OF] = 1 + 1, -+ [ASN1_OP_END_SET] = 1, -+ [ASN1_OP_END_SET_OF] = 1 + 1, -+ [ASN1_OP_END_SEQ_ACT] = 1 + 1, -+ [ASN1_OP_END_SEQ_OF_ACT] = 1 + 1 + 1, -+ [ASN1_OP_END_SET_ACT] = 1 + 1, -+ [ASN1_OP_END_SET_OF_ACT] = 1 + 1 + 1, -+}; -+ -+/* -+ * Find the length of an indefinite length object -+ */ -+static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, -+ const char **_errmsg, size_t *_err_dp) -+{ -+ unsigned char tag, tmp; -+ size_t dp = 0, len, n; -+ int indef_level = 1; -+ -+next_tag: -+ if (unlikely(datalen - dp < 2)) { -+ if (datalen == dp) -+ goto missing_eoc; -+ goto data_overrun_error; -+ } -+ -+ /* Extract a tag from the data */ -+ tag = data[dp++]; -+ if (tag == 0) { -+ /* It appears to be an EOC. */ -+ if (data[dp++] != 0) -+ goto invalid_eoc; -+ if (--indef_level <= 0) -+ return dp; -+ goto next_tag; -+ } -+ -+ if (unlikely((tag & 0x1f) == 0x1f)) { -+ do { -+ if (unlikely(datalen - dp < 2)) -+ goto data_overrun_error; -+ tmp = data[dp++]; -+ } while (tmp & 0x80); -+ } -+ -+ /* Extract the length */ -+ len = data[dp++]; -+ if (len < 0x7f) { -+ dp += len; -+ goto next_tag; -+ } -+ -+ if (unlikely(len == 0x80)) { -+ /* Indefinite length */ -+ if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) -+ goto indefinite_len_primitive; -+ indef_level++; -+ goto next_tag; -+ } -+ -+ n = len - 0x80; -+ if (unlikely(n > sizeof(size_t) - 1)) -+ goto length_too_long; -+ if (unlikely(n > datalen - dp)) -+ goto data_overrun_error; -+ for (len = 0; n > 0; n--) { -+ len <<= 8; -+ len |= data[dp++]; -+ } -+ dp += len; -+ goto next_tag; -+ -+length_too_long: -+ *_errmsg = "Unsupported length"; -+ goto error; -+indefinite_len_primitive: -+ *_errmsg = "Indefinite len primitive not permitted"; -+ goto error; -+invalid_eoc: -+ *_errmsg = "Invalid length EOC"; -+ goto error; -+data_overrun_error: -+ *_errmsg = "Data overrun error"; -+ goto error; -+missing_eoc: -+ *_errmsg = "Missing EOC in indefinite len cons"; -+error: -+ *_err_dp = dp; -+ return -1; -+} -+ -+/** -+ * asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern -+ * @decoder: The decoder definition (produced by asn1_compiler) -+ * @context: The caller's context (to be passed to the action functions) -+ * @data: The encoded data -+ * @datasize: The size of the encoded data -+ * -+ * Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern -+ * produced by asn1_compiler. Action functions are called on marked tags to -+ * allow the caller to retrieve significant data. -+ * -+ * LIMITATIONS: -+ * -+ * To keep down the amount of stack used by this function, the following limits -+ * have been imposed: -+ * -+ * (1) This won't handle datalen > 65535 without increasing the size of the -+ * cons stack elements and length_too_long checking. -+ * -+ * (2) The stack of constructed types is 10 deep. If the depth of non-leaf -+ * constructed types exceeds this, the decode will fail. -+ * -+ * (3) The SET type (not the SET OF type) isn't really supported as tracking -+ * what members of the set have been seen is a pain. -+ */ -+int asn1_ber_decoder(const struct asn1_decoder *decoder, -+ void *context, -+ const unsigned char *data, -+ size_t datalen) -+{ -+ const unsigned char *machine = decoder->machine; -+ const asn1_action_t *actions = decoder->actions; -+ size_t machlen = decoder->machlen; -+ enum asn1_opcode op; -+ unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0; -+ const char *errmsg; -+ size_t pc = 0, dp = 0, tdp = 0, len = 0; -+ int ret; -+ -+ unsigned char flags = 0; -+#define FLAG_INDEFINITE_LENGTH 0x01 -+#define FLAG_MATCHED 0x02 -+#define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag -+ * - ie. whether or not we are going to parse -+ * a compound type. -+ */ -+ -+#define NR_CONS_STACK 10 -+ unsigned short cons_dp_stack[NR_CONS_STACK]; -+ unsigned short cons_datalen_stack[NR_CONS_STACK]; -+ unsigned char cons_hdrlen_stack[NR_CONS_STACK]; -+#define NR_JUMP_STACK 10 -+ unsigned char jump_stack[NR_JUMP_STACK]; -+ -+ if (datalen > 65535) -+ return -EMSGSIZE; -+ -+next_op: -+ pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n", -+ pc, machlen, dp, datalen, csp, jsp); -+ if (unlikely(pc >= machlen)) -+ goto machine_overrun_error; -+ op = machine[pc]; -+ if (unlikely(pc + asn1_op_lengths[op] > machlen)) -+ goto machine_overrun_error; -+ -+ /* If this command is meant to match a tag, then do that before -+ * evaluating the command. -+ */ -+ if (op <= ASN1_OP__MATCHES_TAG) { -+ unsigned char tmp; -+ -+ /* Skip conditional matches if possible */ -+ if ((op & ASN1_OP_MATCH__COND && -+ flags & FLAG_MATCHED) || -+ dp == datalen) { -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ } -+ -+ flags = 0; -+ hdr = 2; -+ -+ /* Extract a tag from the data */ -+ if (unlikely(dp >= datalen - 1)) -+ goto data_overrun_error; -+ tag = data[dp++]; -+ if (unlikely((tag & 0x1f) == 0x1f)) -+ goto long_tag_not_supported; -+ -+ if (op & ASN1_OP_MATCH__ANY) { -+ pr_debug("- any %02x\n", tag); -+ } else { -+ /* Extract the tag from the machine -+ * - Either CONS or PRIM are permitted in the data if -+ * CONS is not set in the op stream, otherwise CONS -+ * is mandatory. -+ */ -+ optag = machine[pc + 1]; -+ flags |= optag & FLAG_CONS; -+ -+ /* Determine whether the tag matched */ -+ tmp = optag ^ tag; -+ tmp &= ~(optag & ASN1_CONS_BIT); -+ pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp); -+ if (tmp != 0) { -+ /* All odd-numbered tags are MATCH_OR_SKIP. */ -+ if (op & ASN1_OP_MATCH__SKIP) { -+ pc += asn1_op_lengths[op]; -+ dp--; -+ goto next_op; -+ } -+ goto tag_mismatch; -+ } -+ } -+ flags |= FLAG_MATCHED; -+ -+ len = data[dp++]; -+ if (len > 0x7f) { -+ if (unlikely(len == 0x80)) { -+ /* Indefinite length */ -+ if (unlikely(!(tag & ASN1_CONS_BIT))) -+ goto indefinite_len_primitive; -+ flags |= FLAG_INDEFINITE_LENGTH; -+ if (unlikely(2 > datalen - dp)) -+ goto data_overrun_error; -+ } else { -+ int n = len - 0x80; -+ if (unlikely(n > 2)) -+ goto length_too_long; -+ if (unlikely(dp >= datalen - n)) -+ goto data_overrun_error; -+ hdr += n; -+ for (len = 0; n > 0; n--) { -+ len <<= 8; -+ len |= data[dp++]; -+ } -+ if (unlikely(len > datalen - dp)) -+ goto data_overrun_error; -+ } -+ } -+ -+ if (flags & FLAG_CONS) { -+ /* For expected compound forms, we stack the positions -+ * of the start and end of the data. -+ */ -+ if (unlikely(csp >= NR_CONS_STACK)) -+ goto cons_stack_overflow; -+ cons_dp_stack[csp] = dp; -+ cons_hdrlen_stack[csp] = hdr; -+ if (!(flags & FLAG_INDEFINITE_LENGTH)) { -+ cons_datalen_stack[csp] = datalen; -+ datalen = dp + len; -+ } else { -+ cons_datalen_stack[csp] = 0; -+ } -+ csp++; -+ } -+ -+ pr_debug("- TAG: %02x %zu%s\n", -+ tag, len, flags & FLAG_CONS ? " CONS" : ""); -+ tdp = dp; -+ } -+ -+ /* Decide how to handle the operation */ -+ switch (op) { -+ case ASN1_OP_MATCH_ANY_ACT: -+ case ASN1_OP_COND_MATCH_ANY_ACT: -+ ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); -+ if (ret < 0) -+ return ret; -+ goto skip_data; -+ -+ case ASN1_OP_MATCH_ACT: -+ case ASN1_OP_MATCH_ACT_OR_SKIP: -+ case ASN1_OP_COND_MATCH_ACT_OR_SKIP: -+ ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len); -+ if (ret < 0) -+ return ret; -+ goto skip_data; -+ -+ case ASN1_OP_MATCH: -+ case ASN1_OP_MATCH_OR_SKIP: -+ case ASN1_OP_MATCH_ANY: -+ case ASN1_OP_COND_MATCH_OR_SKIP: -+ case ASN1_OP_COND_MATCH_ANY: -+ skip_data: -+ if (!(flags & FLAG_CONS)) { -+ if (flags & FLAG_INDEFINITE_LENGTH) { -+ len = asn1_find_indefinite_length( -+ data + dp, datalen - dp, &errmsg, &dp); -+ if (len < 0) -+ goto error; -+ } -+ pr_debug("- LEAF: %zu\n", len); -+ dp += len; -+ } -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ -+ case ASN1_OP_MATCH_JUMP: -+ case ASN1_OP_MATCH_JUMP_OR_SKIP: -+ case ASN1_OP_COND_MATCH_JUMP_OR_SKIP: -+ pr_debug("- MATCH_JUMP\n"); -+ if (unlikely(jsp == NR_JUMP_STACK)) -+ goto jump_stack_overflow; -+ jump_stack[jsp++] = pc + asn1_op_lengths[op]; -+ pc = machine[pc + 2]; -+ goto next_op; -+ -+ case ASN1_OP_COND_FAIL: -+ if (unlikely(!(flags & FLAG_MATCHED))) -+ goto tag_mismatch; -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ -+ case ASN1_OP_COMPLETE: -+ if (unlikely(jsp != 0 || csp != 0)) { -+ pr_err("ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n", -+ jsp, csp); -+ return -EBADMSG; -+ } -+ return 0; -+ -+ case ASN1_OP_END_SET: -+ case ASN1_OP_END_SET_ACT: -+ if (unlikely(!(flags & FLAG_MATCHED))) -+ goto tag_mismatch; -+ case ASN1_OP_END_SEQ: -+ case ASN1_OP_END_SET_OF: -+ case ASN1_OP_END_SEQ_OF: -+ case ASN1_OP_END_SEQ_ACT: -+ case ASN1_OP_END_SET_OF_ACT: -+ case ASN1_OP_END_SEQ_OF_ACT: -+ if (unlikely(csp <= 0)) -+ goto cons_stack_underflow; -+ csp--; -+ tdp = cons_dp_stack[csp]; -+ hdr = cons_hdrlen_stack[csp]; -+ len = datalen; -+ datalen = cons_datalen_stack[csp]; -+ pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n", -+ tdp, dp, len, datalen); -+ if (datalen == 0) { -+ /* Indefinite length - check for the EOC. */ -+ datalen = len; -+ if (unlikely(datalen - dp < 2)) -+ goto data_overrun_error; -+ if (data[dp++] != 0) { -+ if (op & ASN1_OP_END__OF) { -+ dp--; -+ csp++; -+ pc = machine[pc + 1]; -+ pr_debug("- continue\n"); -+ goto next_op; -+ } -+ goto missing_eoc; -+ } -+ if (data[dp++] != 0) -+ goto invalid_eoc; -+ len = dp - tdp - 2; -+ } else { -+ if (dp < len && (op & ASN1_OP_END__OF)) { -+ datalen = len; -+ csp++; -+ pc = machine[pc + 1]; -+ pr_debug("- continue\n"); -+ goto next_op; -+ } -+ if (dp != len) -+ goto cons_length_error; -+ len -= tdp; -+ pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp); -+ } -+ -+ if (op & ASN1_OP_END__ACT) { -+ unsigned char act; -+ if (op & ASN1_OP_END__OF) -+ act = machine[pc + 2]; -+ else -+ act = machine[pc + 1]; -+ ret = actions[act](context, hdr, 0, data + tdp, len); -+ } -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ -+ case ASN1_OP_ACT: -+ ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ -+ case ASN1_OP_RETURN: -+ if (unlikely(jsp <= 0)) -+ goto jump_stack_underflow; -+ pc = jump_stack[--jsp]; -+ goto next_op; -+ -+ default: -+ break; -+ } -+ -+ /* Shouldn't reach here */ -+ pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op); -+ return -EBADMSG; -+ -+data_overrun_error: -+ errmsg = "Data overrun error"; -+ goto error; -+machine_overrun_error: -+ errmsg = "Machine overrun error"; -+ goto error; -+jump_stack_underflow: -+ errmsg = "Jump stack underflow"; -+ goto error; -+jump_stack_overflow: -+ errmsg = "Jump stack overflow"; -+ goto error; -+cons_stack_underflow: -+ errmsg = "Cons stack underflow"; -+ goto error; -+cons_stack_overflow: -+ errmsg = "Cons stack overflow"; -+ goto error; -+cons_length_error: -+ errmsg = "Cons length error"; -+ goto error; -+missing_eoc: -+ errmsg = "Missing EOC in indefinite len cons"; -+ goto error; -+invalid_eoc: -+ errmsg = "Invalid length EOC"; -+ goto error; -+length_too_long: -+ errmsg = "Unsupported length"; -+ goto error; -+indefinite_len_primitive: -+ errmsg = "Indefinite len primitive not permitted"; -+ goto error; -+tag_mismatch: -+ errmsg = "Unexpected tag"; -+ goto error; -+long_tag_not_supported: -+ errmsg = "Long tag not supported"; -+error: -+ pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n", -+ errmsg, pc, dp, optag, tag, len); -+ return -EBADMSG; -+} -+EXPORT_SYMBOL_GPL(asn1_ber_decoder); --- -1.7.12.1 - - -From 686b0b5e3549b711c0bcc405d833697ff5e2344d Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Mon, 24 Sep 2012 17:11:27 +0100 -Subject: [PATCH 16/37] MPILIB: Provide a function to read raw data into an - MPI - -Provide a function to read raw data of a predetermined size into an MPI rather -than expecting the size to be encoded within the data. The data is assumed to -represent an unsigned integer, and the resulting MPI will be positive. - -The function looks like this: - - MPI mpi_read_raw_data(const void *, size_t); - -This is useful for reading ASN.1 integer primitives where the length is encoded -in the ASN.1 metadata. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - include/linux/mpi.h | 1 + - lib/mpi/mpicoder.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 56 insertions(+) - -diff --git a/include/linux/mpi.h b/include/linux/mpi.h -index d02cca6..5af1b81 100644 ---- a/include/linux/mpi.h -+++ b/include/linux/mpi.h -@@ -76,6 +76,7 @@ void mpi_swap(MPI a, MPI b); - - /*-- mpicoder.c --*/ - MPI do_encode_md(const void *sha_buffer, unsigned nbits); -+MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes); - MPI mpi_read_from_buffer(const void *buffer, unsigned *ret_nread); - int mpi_fromstr(MPI val, const char *str); - u32 mpi_get_keyid(MPI a, u32 *keyid); -diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c -index f0fa659..3962b7f 100644 ---- a/lib/mpi/mpicoder.c -+++ b/lib/mpi/mpicoder.c -@@ -18,10 +18,65 @@ - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -+#include <linux/bitops.h> -+#include <asm-generic/bitops/count_zeros.h> - #include "mpi-internal.h" - - #define MAX_EXTERN_MPI_BITS 16384 - -+/** -+ * mpi_read_raw_data - Read a raw byte stream as a positive integer -+ * @xbuffer: The data to read -+ * @nbytes: The amount of data to read -+ */ -+MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes) -+{ -+ const uint8_t *buffer = xbuffer; -+ int i, j; -+ unsigned nbits, nlimbs; -+ mpi_limb_t a; -+ MPI val = NULL; -+ -+ while (nbytes >= 0 && buffer[0] == 0) { -+ buffer++; -+ nbytes--; -+ } -+ -+ nbits = nbytes * 8; -+ if (nbits > MAX_EXTERN_MPI_BITS) { -+ pr_info("MPI: mpi too large (%u bits)\n", nbits); -+ return NULL; -+ } -+ if (nbytes > 0) -+ nbits -= count_leading_zeros(buffer[0]); -+ else -+ nbits = 0; -+ -+ nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; -+ val = mpi_alloc(nlimbs); -+ if (!val) -+ return NULL; -+ val->nbits = nbits; -+ val->sign = 0; -+ val->nlimbs = nlimbs; -+ -+ if (nbytes > 0) { -+ i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; -+ i %= BYTES_PER_MPI_LIMB; -+ for (j = nlimbs; j > 0; j--) { -+ a = 0; -+ for (; i < BYTES_PER_MPI_LIMB; i++) { -+ a <<= 8; -+ a |= *buffer++; -+ } -+ i = 0; -+ val->d[j - 1] = a; -+ } -+ } -+ return val; -+} -+EXPORT_SYMBOL_GPL(mpi_read_raw_data); -+ - MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) - { - const uint8_t *buffer = xbuffer; --- -1.7.12.1 - - -From c6ca1b7770b65d0639fb84a7afead457ff22c8d4 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Mon, 24 Sep 2012 17:11:48 +0100 -Subject: [PATCH 17/37] X.509: Add a crypto key parser for binary (DER) X.509 - certificates - -Add a crypto key parser for binary (DER) encoded X.509 certificates. The -certificate is parsed and, if possible, the signature is verified. - -An X.509 key can be added like this: - - # keyctl padd crypto bar @s </tmp/x509.cert - 15768135 - -and displayed like this: - - # cat /proc/keys - 00f09a47 I--Q--- 1 perm 39390000 0 0 asymmetri bar: X509.RSA e9fd6d08 [] - -Note that this only works with binary certificates. PEM encoded certificates -are ignored by the parser. - -Note also that the X.509 key ID is not congruent with the PGP key ID, but for -the moment, they will match. - -If a NULL or "" name is given to add_key(), then the parser will generate a key -description from the CertificateSerialNumber and Name fields of the -TBSCertificate: - - 00aefc4e I--Q--- 1 perm 39390000 0 0 asymmetri bfbc0cd76d050ea4:/C=GB/L=Cambridge/O=Red Hat/CN=kernel key: X509.RSA 0c688c7b [] - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - crypto/asymmetric_keys/.gitignore | 1 + - crypto/asymmetric_keys/Kconfig | 10 + - crypto/asymmetric_keys/Makefile | 17 + - crypto/asymmetric_keys/x509.asn1 | 60 ++++ - crypto/asymmetric_keys/x509_cert_parser.c | 497 ++++++++++++++++++++++++++++++ - crypto/asymmetric_keys/x509_parser.h | 36 +++ - crypto/asymmetric_keys/x509_public_key.c | 207 +++++++++++++ - crypto/asymmetric_keys/x509_rsakey.asn1 | 4 + - 8 files changed, 832 insertions(+) - create mode 100644 crypto/asymmetric_keys/.gitignore - create mode 100644 crypto/asymmetric_keys/x509.asn1 - create mode 100644 crypto/asymmetric_keys/x509_cert_parser.c - create mode 100644 crypto/asymmetric_keys/x509_parser.h - create mode 100644 crypto/asymmetric_keys/x509_public_key.c - create mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1 - -diff --git a/crypto/asymmetric_keys/.gitignore b/crypto/asymmetric_keys/.gitignore -new file mode 100644 -index 0000000..ee32837 ---- /dev/null -+++ b/crypto/asymmetric_keys/.gitignore -@@ -0,0 +1 @@ -+*-asn1.[ch] -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -index 561759d..6d2c2ea 100644 ---- a/crypto/asymmetric_keys/Kconfig -+++ b/crypto/asymmetric_keys/Kconfig -@@ -25,4 +25,14 @@ config PUBLIC_KEY_ALGO_RSA - help - This option enables support for the RSA algorithm (PKCS#1, RFC3447). - -+config X509_CERTIFICATE_PARSER -+ tristate "X.509 certificate parser" -+ depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE -+ select ASN1 -+ select OID_REGISTRY -+ help -+ This option procides support for parsing X.509 format blobs for key -+ data and provides the ability to instantiate a crypto key from a -+ public key packet found inside the certificate. -+ - endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index 7c92691..0727204 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -8,3 +8,20 @@ asymmetric_keys-y := asymmetric_type.o signature.o - - obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o - obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o -+ -+# -+# X.509 Certificate handling -+# -+obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o -+x509_key_parser-y := \ -+ x509-asn1.o \ -+ x509_rsakey-asn1.o \ -+ x509_cert_parser.o \ -+ x509_public_key.o -+ -+$(obj)/x509_cert_parser.o: $(obj)/x509-asn1.h $(obj)/x509_rsakey-asn1.h -+$(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h -+$(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h -+ -+clean-files += x509-asn1.c x509-asn1.h -+clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h -diff --git a/crypto/asymmetric_keys/x509.asn1 b/crypto/asymmetric_keys/x509.asn1 -new file mode 100644 -index 0000000..bf32b3d ---- /dev/null -+++ b/crypto/asymmetric_keys/x509.asn1 -@@ -0,0 +1,60 @@ -+Certificate ::= SEQUENCE { -+ tbsCertificate TBSCertificate ({ x509_note_tbs_certificate }), -+ signatureAlgorithm AlgorithmIdentifier, -+ signature BIT STRING ({ x509_note_signature }) -+ } -+ -+TBSCertificate ::= SEQUENCE { -+ version [ 0 ] Version DEFAULT, -+ serialNumber CertificateSerialNumber, -+ signature AlgorithmIdentifier ({ x509_note_pkey_algo }), -+ issuer Name ({ x509_note_issuer }), -+ validity Validity, -+ subject Name ({ x509_note_subject }), -+ subjectPublicKeyInfo SubjectPublicKeyInfo, -+ issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL, -+ subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL, -+ extensions [ 3 ] Extensions OPTIONAL -+ } -+ -+Version ::= INTEGER -+CertificateSerialNumber ::= INTEGER -+ -+AlgorithmIdentifier ::= SEQUENCE { -+ algorithm OBJECT IDENTIFIER ({ x509_note_OID }), -+ parameters ANY OPTIONAL -+} -+ -+Name ::= SEQUENCE OF RelativeDistinguishedName -+ -+RelativeDistinguishedName ::= SET OF AttributeValueAssertion -+ -+AttributeValueAssertion ::= SEQUENCE { -+ attributeType OBJECT IDENTIFIER ({ x509_note_OID }), -+ attributeValue ANY ({ x509_extract_name_segment }) -+ } -+ -+Validity ::= SEQUENCE { -+ notBefore Time ({ x509_note_not_before }), -+ notAfter Time ({ x509_note_not_after }) -+ } -+ -+Time ::= CHOICE { -+ utcTime UTCTime, -+ generalTime GeneralizedTime -+ } -+ -+SubjectPublicKeyInfo ::= SEQUENCE { -+ algorithm AlgorithmIdentifier, -+ subjectPublicKey BIT STRING ({ x509_extract_key_data }) -+ } -+ -+UniqueIdentifier ::= BIT STRING -+ -+Extensions ::= SEQUENCE OF Extension -+ -+Extension ::= SEQUENCE { -+ extnid OBJECT IDENTIFIER ({ x509_note_OID }), -+ critical BOOLEAN DEFAULT, -+ extnValue OCTET STRING ({ x509_process_extension }) -+ } -diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c -new file mode 100644 -index 0000000..8fcac94 ---- /dev/null -+++ b/crypto/asymmetric_keys/x509_cert_parser.c -@@ -0,0 +1,497 @@ -+/* X.509 certificate parser -+ * -+ * Copyright (C) 2012 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) "X.509: "fmt -+#include <linux/kernel.h> -+#include <linux/slab.h> -+#include <linux/err.h> -+#include <linux/oid_registry.h> -+#include "public_key.h" -+#include "x509_parser.h" -+#include "x509-asn1.h" -+#include "x509_rsakey-asn1.h" -+ -+struct x509_parse_context { -+ struct x509_certificate *cert; /* Certificate being constructed */ -+ unsigned long data; /* Start of data */ -+ const void *cert_start; /* Start of cert content */ -+ const void *key; /* Key data */ -+ size_t key_size; /* Size of key data */ -+ enum OID last_oid; /* Last OID encountered */ -+ enum OID algo_oid; /* Algorithm OID */ -+ unsigned char nr_mpi; /* Number of MPIs stored */ -+ u8 o_size; /* Size of organizationName (O) */ -+ u8 cn_size; /* Size of commonName (CN) */ -+ u8 email_size; /* Size of emailAddress */ -+ u16 o_offset; /* Offset of organizationName (O) */ -+ u16 cn_offset; /* Offset of commonName (CN) */ -+ u16 email_offset; /* Offset of emailAddress */ -+}; -+ -+/* -+ * Free an X.509 certificate -+ */ -+void x509_free_certificate(struct x509_certificate *cert) -+{ -+ if (cert) { -+ public_key_destroy(cert->pub); -+ kfree(cert->issuer); -+ kfree(cert->subject); -+ kfree(cert->fingerprint); -+ kfree(cert->authority); -+ kfree(cert); -+ } -+} -+ -+/* -+ * Parse an X.509 certificate -+ */ -+struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) -+{ -+ struct x509_certificate *cert; -+ struct x509_parse_context *ctx; -+ long ret; -+ -+ ret = -ENOMEM; -+ cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL); -+ if (!cert) -+ goto error_no_cert; -+ cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL); -+ if (!cert->pub) -+ goto error_no_ctx; -+ ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL); -+ if (!ctx) -+ goto error_no_ctx; -+ -+ ctx->cert = cert; -+ ctx->data = (unsigned long)data; -+ -+ /* Attempt to decode the certificate */ -+ ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen); -+ if (ret < 0) -+ goto error_decode; -+ -+ /* Decode the public key */ -+ ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx, -+ ctx->key, ctx->key_size); -+ if (ret < 0) -+ goto error_decode; -+ -+ kfree(ctx); -+ return cert; -+ -+error_decode: -+ kfree(ctx); -+error_no_ctx: -+ x509_free_certificate(cert); -+error_no_cert: -+ return ERR_PTR(ret); -+} -+ -+/* -+ * Note an OID when we find one for later processing when we know how -+ * to interpret it. -+ */ -+int x509_note_OID(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ ctx->last_oid = look_up_OID(value, vlen); -+ if (ctx->last_oid == OID__NR) { -+ char buffer[50]; -+ sprint_oid(value, vlen, buffer, sizeof(buffer)); -+ pr_debug("Unknown OID: [%zu] %s\n", -+ (unsigned long)value - ctx->data, buffer); -+ } -+ return 0; -+} -+ -+/* -+ * Save the position of the TBS data so that we can check the signature over it -+ * later. -+ */ -+int x509_note_tbs_certificate(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ pr_debug("x509_note_tbs_certificate(,%zu,%02x,%ld,%zu)!\n", -+ hdrlen, tag, (unsigned long)value - ctx->data, vlen); -+ -+ ctx->cert->tbs = value - hdrlen; -+ ctx->cert->tbs_size = vlen + hdrlen; -+ return 0; -+} -+ -+/* -+ * Record the public key algorithm -+ */ -+int x509_note_pkey_algo(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ pr_debug("PubKey Algo: %u\n", ctx->last_oid); -+ -+ switch (ctx->last_oid) { -+ case OID_md2WithRSAEncryption: -+ case OID_md3WithRSAEncryption: -+ default: -+ return -ENOPKG; /* Unsupported combination */ -+ -+ case OID_md4WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_MD5; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha1WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA1; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha256WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA256; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha384WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA384; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha512WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA512; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha224WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA224; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ } -+ -+ ctx->algo_oid = ctx->last_oid; -+ return 0; -+} -+ -+/* -+ * Note the whereabouts and type of the signature. -+ */ -+int x509_note_signature(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ pr_debug("Signature type: %u size %zu\n", ctx->last_oid, vlen); -+ -+ if (ctx->last_oid != ctx->algo_oid) { -+ pr_warn("Got cert with pkey (%u) and sig (%u) algorithm OIDs\n", -+ ctx->algo_oid, ctx->last_oid); -+ return -EINVAL; -+ } -+ -+ ctx->cert->sig = value; -+ ctx->cert->sig_size = vlen; -+ return 0; -+} -+ -+/* -+ * Note some of the name segments from which we'll fabricate a name. -+ */ -+int x509_extract_name_segment(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ switch (ctx->last_oid) { -+ case OID_commonName: -+ ctx->cn_size = vlen; -+ ctx->cn_offset = (unsigned long)value - ctx->data; -+ break; -+ case OID_organizationName: -+ ctx->o_size = vlen; -+ ctx->o_offset = (unsigned long)value - ctx->data; -+ break; -+ case OID_email_address: -+ ctx->email_size = vlen; -+ ctx->email_offset = (unsigned long)value - ctx->data; -+ break; -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Fabricate and save the issuer and subject names -+ */ -+static int x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen, -+ unsigned char tag, -+ char **_name, size_t vlen) -+{ -+ const void *name, *data = (const void *)ctx->data; -+ size_t namesize; -+ char *buffer; -+ -+ if (*_name) -+ return -EINVAL; -+ -+ /* Empty name string if no material */ -+ if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) { -+ buffer = kmalloc(1, GFP_KERNEL); -+ if (!buffer) -+ return -ENOMEM; -+ buffer[0] = 0; -+ goto done; -+ } -+ -+ if (ctx->cn_size && ctx->o_size) { -+ /* Consider combining O and CN, but use only the CN if it is -+ * prefixed by the O, or a significant portion thereof. -+ */ -+ namesize = ctx->cn_size; -+ name = data + ctx->cn_offset; -+ if (ctx->cn_size >= ctx->o_size && -+ memcmp(data + ctx->cn_offset, data + ctx->o_offset, -+ ctx->o_size) == 0) -+ goto single_component; -+ if (ctx->cn_size >= 7 && -+ ctx->o_size >= 7 && -+ memcmp(data + ctx->cn_offset, data + ctx->o_offset, 7) == 0) -+ goto single_component; -+ -+ buffer = kmalloc(ctx->o_size + 2 + ctx->cn_size + 1, -+ GFP_KERNEL); -+ if (!buffer) -+ return -ENOMEM; -+ -+ memcpy(buffer, -+ data + ctx->o_offset, ctx->o_size); -+ buffer[ctx->o_size + 0] = ':'; -+ buffer[ctx->o_size + 1] = ' '; -+ memcpy(buffer + ctx->o_size + 2, -+ data + ctx->cn_offset, ctx->cn_size); -+ buffer[ctx->o_size + 2 + ctx->cn_size] = 0; -+ goto done; -+ -+ } else if (ctx->cn_size) { -+ namesize = ctx->cn_size; -+ name = data + ctx->cn_offset; -+ } else if (ctx->o_size) { -+ namesize = ctx->o_size; -+ name = data + ctx->o_offset; -+ } else { -+ namesize = ctx->email_size; -+ name = data + ctx->email_offset; -+ } -+ -+single_component: -+ buffer = kmalloc(namesize + 1, GFP_KERNEL); -+ if (!buffer) -+ return -ENOMEM; -+ memcpy(buffer, name, namesize); -+ buffer[namesize] = 0; -+ -+done: -+ *_name = buffer; -+ ctx->cn_size = 0; -+ ctx->o_size = 0; -+ ctx->email_size = 0; -+ return 0; -+} -+ -+int x509_note_issuer(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen); -+} -+ -+int x509_note_subject(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen); -+} -+ -+/* -+ * Extract the data for the public key algorithm -+ */ -+int x509_extract_key_data(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ if (ctx->last_oid != OID_rsaEncryption) -+ return -ENOPKG; -+ -+ /* There seems to be an extraneous 0 byte on the front of the data */ -+ ctx->cert->pkey_algo = PKEY_ALGO_RSA; -+ ctx->key = value + 1; -+ ctx->key_size = vlen - 1; -+ return 0; -+} -+ -+/* -+ * Extract a RSA public key value -+ */ -+int rsa_extract_mpi(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ MPI mpi; -+ -+ if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) { -+ pr_err("Too many public key MPIs in certificate\n"); -+ return -EBADMSG; -+ } -+ -+ mpi = mpi_read_raw_data(value, vlen); -+ if (!mpi) -+ return -ENOMEM; -+ -+ ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi; -+ return 0; -+} -+ -+/* -+ * Process certificate extensions that are used to qualify the certificate. -+ */ -+int x509_process_extension(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ const unsigned char *v = value; -+ char *f; -+ int i; -+ -+ pr_debug("Extension: %u\n", ctx->last_oid); -+ -+ if (ctx->last_oid == OID_subjectKeyIdentifier) { -+ /* Get hold of the key fingerprint */ -+ if (vlen < 3) -+ return -EBADMSG; -+ if (v[0] != ASN1_OTS || v[1] != vlen - 2) -+ return -EBADMSG; -+ v += 2; -+ vlen -= 2; -+ -+ f = kmalloc(vlen * 2 + 1, GFP_KERNEL); -+ if (!f) -+ return -ENOMEM; -+ for (i = 0; i < vlen; i++) -+ sprintf(f + i * 2, "%02x", v[i]); -+ pr_debug("fingerprint %s\n", f); -+ ctx->cert->fingerprint = f; -+ return 0; -+ } -+ -+ if (ctx->last_oid == OID_authorityKeyIdentifier) { -+ /* Get hold of the CA key fingerprint */ -+ if (vlen < 5) -+ return -EBADMSG; -+ if (v[0] != (ASN1_SEQ | (ASN1_CONS << 5)) || -+ v[1] != vlen - 2 || -+ v[2] != (ASN1_CONT << 6) || -+ v[3] != vlen - 4) -+ return -EBADMSG; -+ v += 4; -+ vlen -= 4; -+ -+ f = kmalloc(vlen * 2 + 1, GFP_KERNEL); -+ if (!f) -+ return -ENOMEM; -+ for (i = 0; i < vlen; i++) -+ sprintf(f + i * 2, "%02x", v[i]); -+ pr_debug("authority %s\n", f); -+ ctx->cert->authority = f; -+ return 0; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Record a certificate time. -+ */ -+static int x509_note_time(time_t *_time, size_t hdrlen, -+ unsigned char tag, -+ const unsigned char *value, size_t vlen) -+{ -+ unsigned YY, MM, DD, hh, mm, ss; -+ const unsigned char *p = value; -+ -+#define dec2bin(X) ((X) - '0') -+#define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; }) -+ -+ if (tag == ASN1_UNITIM) { -+ /* UTCTime: YYMMDDHHMMSSZ */ -+ if (vlen != 13) -+ goto unsupported_time; -+ YY = DD2bin(p); -+ if (YY > 50) -+ YY += 1900; -+ else -+ YY += 2000; -+ } else if (tag == ASN1_GENTIM) { -+ /* GenTime: YYYYMMDDHHMMSSZ */ -+ if (vlen != 15) -+ goto unsupported_time; -+ YY = DD2bin(p) * 100 + DD2bin(p); -+ } else { -+ goto unsupported_time; -+ } -+ -+ MM = DD2bin(p); -+ DD = DD2bin(p); -+ hh = DD2bin(p); -+ mm = DD2bin(p); -+ ss = DD2bin(p); -+ -+ if (*p != 'Z') -+ goto unsupported_time; -+ -+ *_time = mktime(YY, MM, DD, hh, mm, ss); -+ return 0; -+ -+unsupported_time: -+ pr_debug("Got unsupported time [tag %02x]: '%*.*s'\n", -+ tag, (int)vlen, (int)vlen, value); -+ return -EBADMSG; -+} -+ -+int x509_note_not_before(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ return x509_note_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen); -+} -+ -+int x509_note_not_after(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ return x509_note_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); -+} -diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h -new file mode 100644 -index 0000000..635053f ---- /dev/null -+++ b/crypto/asymmetric_keys/x509_parser.h -@@ -0,0 +1,36 @@ -+/* X.509 certificate parser internal definitions -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#include <crypto/public_key.h> -+ -+struct x509_certificate { -+ struct x509_certificate *next; -+ struct public_key *pub; /* Public key details */ -+ char *issuer; /* Name of certificate issuer */ -+ char *subject; /* Name of certificate subject */ -+ char *fingerprint; /* Key fingerprint as hex */ -+ char *authority; /* Authority key fingerprint as hex */ -+ time_t valid_from; -+ time_t valid_to; -+ enum pkey_algo pkey_algo : 8; /* Public key algorithm */ -+ enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ -+ enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ -+ const void *tbs; /* Signed data */ -+ size_t tbs_size; /* Size of signed data */ -+ const void *sig; /* Signature data */ -+ size_t sig_size; /* Size of sigature */ -+}; -+ -+/* -+ * x509_cert_parser.c -+ */ -+extern void x509_free_certificate(struct x509_certificate *cert); -+extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -new file mode 100644 -index 0000000..716917c ---- /dev/null -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -0,0 +1,207 @@ -+/* Instantiate a public key crypto key from an X.509 Certificate -+ * -+ * Copyright (C) 2012 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) "X.509: "fmt -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/slab.h> -+#include <linux/err.h> -+#include <linux/mpi.h> -+#include <linux/asn1_decoder.h> -+#include <keys/asymmetric-subtype.h> -+#include <keys/asymmetric-parser.h> -+#include <crypto/hash.h> -+#include "asymmetric_keys.h" -+#include "public_key.h" -+#include "x509_parser.h" -+ -+static const -+struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = { -+ [PKEY_ALGO_DSA] = NULL, -+#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ -+ defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) -+ [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, -+#endif -+}; -+ -+/* -+ * Check the signature on a certificate using the provided public key -+ */ -+static int x509_check_signature(const struct public_key *pub, -+ const struct x509_certificate *cert) -+{ -+ struct public_key_signature *sig; -+ struct crypto_shash *tfm; -+ struct shash_desc *desc; -+ size_t digest_size, desc_size; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ /* Allocate the hashing algorithm we're going to need and find out how -+ * big the hash operational data will be. -+ */ -+ tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0); -+ if (IS_ERR(tfm)) -+ return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); -+ -+ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); -+ digest_size = crypto_shash_digestsize(tfm); -+ -+ /* We allocate the hash operational data storage on the end of our -+ * context data. -+ */ -+ ret = -ENOMEM; -+ sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); -+ if (!sig) -+ goto error_no_sig; -+ -+ sig->pkey_hash_algo = cert->sig_hash_algo; -+ sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; -+ sig->digest_size = digest_size; -+ -+ desc = (void *)sig + sizeof(*sig); -+ desc->tfm = tfm; -+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; -+ -+ ret = crypto_shash_init(desc); -+ if (ret < 0) -+ goto error; -+ -+ ret = -ENOMEM; -+ sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); -+ if (!sig->rsa.s) -+ goto error; -+ -+ ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); -+ if (ret < 0) -+ goto error_mpi; -+ -+ ret = pub->algo->verify_signature(pub, sig); -+ -+ pr_debug("Cert Verification: %d\n", ret); -+ -+error_mpi: -+ mpi_free(sig->rsa.s); -+error: -+ kfree(sig); -+error_no_sig: -+ crypto_free_shash(tfm); -+ -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; -+} -+ -+/* -+ * Attempt to parse a data blob for a key as an X509 certificate. -+ */ -+static int x509_key_preparse(struct key_preparsed_payload *prep) -+{ -+ struct x509_certificate *cert; -+ time_t now; -+ size_t srlen, sulen; -+ char *desc = NULL; -+ int ret; -+ -+ cert = x509_cert_parse(prep->data, prep->datalen); -+ if (IS_ERR(cert)) -+ return PTR_ERR(cert); -+ -+ pr_devel("Cert Issuer: %s\n", cert->issuer); -+ pr_devel("Cert Subject: %s\n", cert->subject); -+ pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); -+ pr_devel("Cert Valid: %lu - %lu\n", cert->valid_from, cert->valid_to); -+ pr_devel("Cert Signature: %s + %s\n", -+ pkey_algo[cert->sig_pkey_algo], -+ pkey_hash_algo[cert->sig_hash_algo]); -+ -+ if (!cert->fingerprint || !cert->authority) { -+ pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", -+ cert->subject); -+ ret = -EKEYREJECTED; -+ goto error_free_cert; -+ } -+ -+ now = CURRENT_TIME.tv_sec; -+ if (now < cert->valid_from) { -+ pr_warn("Cert %s is not yet valid\n", cert->fingerprint); -+ ret = -EKEYREJECTED; -+ goto error_free_cert; -+ } -+ if (now >= cert->valid_to) { -+ pr_warn("Cert %s has expired\n", cert->fingerprint); -+ ret = -EKEYEXPIRED; -+ goto error_free_cert; -+ } -+ -+ cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo]; -+ cert->pub->id_type = PKEY_ID_X509; -+ -+ /* Check the signature on the key */ -+ if (strcmp(cert->fingerprint, cert->authority) == 0) { -+ ret = x509_check_signature(cert->pub, cert); -+ if (ret < 0) -+ goto error_free_cert; -+ } -+ -+ /* Propose a description */ -+ sulen = strlen(cert->subject); -+ srlen = strlen(cert->fingerprint); -+ ret = -ENOMEM; -+ desc = kmalloc(sulen + 2 + srlen + 1, GFP_KERNEL); -+ if (!desc) -+ goto error_free_cert; -+ memcpy(desc, cert->subject, sulen); -+ desc[sulen] = ':'; -+ desc[sulen + 1] = ' '; -+ memcpy(desc + sulen + 2, cert->fingerprint, srlen); -+ desc[sulen + 2 + srlen] = 0; -+ -+ /* We're pinning the module by being linked against it */ -+ __module_get(public_key_subtype.owner); -+ prep->type_data[0] = &public_key_subtype; -+ prep->type_data[1] = cert->fingerprint; -+ prep->payload = cert->pub; -+ prep->description = desc; -+ prep->quotalen = 100; -+ -+ /* We've finished with the certificate */ -+ cert->pub = NULL; -+ cert->fingerprint = NULL; -+ desc = NULL; -+ ret = 0; -+ -+error_free_cert: -+ x509_free_certificate(cert); -+ return ret; -+} -+ -+static struct asymmetric_key_parser x509_key_parser = { -+ .owner = THIS_MODULE, -+ .name = "x509", -+ .parse = x509_key_preparse, -+}; -+ -+/* -+ * Module stuff -+ */ -+static int __init x509_key_init(void) -+{ -+ return register_asymmetric_key_parser(&x509_key_parser); -+} -+ -+static void __exit x509_key_exit(void) -+{ -+ unregister_asymmetric_key_parser(&x509_key_parser); -+} -+ -+module_init(x509_key_init); -+module_exit(x509_key_exit); -diff --git a/crypto/asymmetric_keys/x509_rsakey.asn1 b/crypto/asymmetric_keys/x509_rsakey.asn1 -new file mode 100644 -index 0000000..4ec7cc6 ---- /dev/null -+++ b/crypto/asymmetric_keys/x509_rsakey.asn1 -@@ -0,0 +1,4 @@ -+RSAPublicKey ::= SEQUENCE { -+ modulus INTEGER ({ rsa_extract_mpi }), -- n -+ publicExponent INTEGER ({ rsa_extract_mpi }) -- e -+ } --- -1.7.12.1 - - -From a4c3000ab42b11536ffc8eb9c1d03a746b424bda Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Wed, 26 Sep 2012 10:09:50 +0100 -Subject: [PATCH 18/37] MODSIGN: Add FIPS policy - -If we're in FIPS mode, we should panic if we fail to verify the signature on a -module or we're asked to load an unsigned module in signature enforcing mode. -Possibly FIPS mode should automatically enable enforcing mode. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - kernel/module.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/kernel/module.c b/kernel/module.c -index 7efb415..3e8b1a7 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -58,6 +58,7 @@ - #include <linux/jump_label.h> - #include <linux/pfn.h> - #include <linux/bsearch.h> -+#include <linux/fips.h> - #include "module-internal.h" - - #define CREATE_TRACE_POINTS -@@ -2467,6 +2468,9 @@ static int module_sig_check(struct load_info *info, - } - - /* Not having a signature is only an error if we're strict. */ -+ if (err < 0 && fips_enabled) -+ panic("Module verification failed with error %d in FIPS mode\n", -+ err); - if (err == -ENOKEY && !sig_enforce) - err = 0; - --- -1.7.12.1 - - -From 86342ab6db2c5b10b08bd9d1064b1779070c2a82 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Wed, 26 Sep 2012 10:09:50 +0100 -Subject: [PATCH 19/37] MODSIGN: Provide gitignore and make clean rules for - extra files - -Provide gitignore and make clean rules for extra files to hide and clean up the -extra files produced by module signing stuff once it is added. Also add a -clean up rule for the module content extractor program used to extract the data -to be signed. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - .gitignore | 14 ++++++++++++++ - Makefile | 1 + - 2 files changed, 15 insertions(+) - -diff --git a/.gitignore b/.gitignore -index 57af07c..0f2f40f 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -14,6 +14,10 @@ - *.o.* - *.a - *.s -+*.ko.unsigned -+*.ko.stripped -+*.ko.stripped.dig -+*.ko.stripped.sig - *.ko - *.so - *.so.dbg -@@ -84,3 +88,13 @@ GTAGS - *.orig - *~ - \#*# -+ -+# -+# Leavings from module signing -+# -+extra_certificates -+signing_key.priv -+signing_key.x509 -+signing_key.x509.keyid -+signing_key.x509.signer -+x509.genkey -diff --git a/Makefile b/Makefile -index 6cdadf4..b4f9eb5 100644 ---- a/Makefile -+++ b/Makefile -@@ -1239,6 +1239,7 @@ clean: $(clean-dirs) - $(call cmd,rmfiles) - @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ - \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ -+ -o -name '*.ko.*' \ - -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ - -o -name '*.symtypes' -o -name 'modules.order' \ - -o -name modules.builtin -o -name '.tmp_*.o.*' \ --- -1.7.12.1 - - -From c631aa86c295b87aa09188d9313cccf41e5db23f Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Wed, 26 Sep 2012 10:09:50 +0100 -Subject: [PATCH 20/37] MODSIGN: Provide Kconfig options - -Provide kernel configuration options for module signing. - -The following configuration options are added: - - CONFIG_MODULE_SIG_SHA1 - CONFIG_MODULE_SIG_SHA224 - CONFIG_MODULE_SIG_SHA256 - CONFIG_MODULE_SIG_SHA384 - CONFIG_MODULE_SIG_SHA512 - -These select the cryptographic hash used to digest the data prior to signing. -Additionally, the crypto module selected will be built into the kernel as it -won't be possible to load it as a module without incurring a circular -dependency when the kernel tries to check its signature. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - init/Kconfig | 38 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - -diff --git a/init/Kconfig b/init/Kconfig -index fa8ccad..00d4579 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1593,12 +1593,50 @@ config MODULE_SIG - is simply appended to the module. For more information see - Documentation/module-signing.txt. - -+ !!!WARNING!!! If you enable this option, you MUST make sure that the -+ module DOES NOT get stripped after being signed. This includes the -+ debuginfo strip done by some packagers (such as rpmbuild) and -+ inclusion into an initramfs that wants the module size reduced. -+ - config MODULE_SIG_FORCE - bool "Require modules to be validly signed" - depends on MODULE_SIG - help - Reject unsigned modules or signed modules for which we don't have a - key. Without this, such modules will simply taint the kernel. -+ -+choice -+ prompt "Which hash algorithm should modules be signed with?" -+ depends on MODULE_SIG -+ help -+ This determines which sort of hashing algorithm will be used during -+ signature generation. This algorithm _must_ be built into the kernel -+ directly so that signature verification can take place. It is not -+ possible to load a signed module containing the algorithm to check -+ the signature on that module. -+ -+config MODULE_SIG_SHA1 -+ bool "Sign modules with SHA-1" -+ select CRYPTO_SHA1 -+ -+config MODULE_SIG_SHA224 -+ bool "Sign modules with SHA-224" -+ select CRYPTO_SHA256 -+ -+config MODULE_SIG_SHA256 -+ bool "Sign modules with SHA-256" -+ select CRYPTO_SHA256 -+ -+config MODULE_SIG_SHA384 -+ bool "Sign modules with SHA-384" -+ select CRYPTO_SHA512 -+ -+config MODULE_SIG_SHA512 -+ bool "Sign modules with SHA-512" -+ select CRYPTO_SHA512 -+ -+endchoice -+ - endif # MODULES - - config INIT_ALL_POSSIBLE --- -1.7.12.1 - - -From 84d1788d1ea47ecfe2d30d0c2081055d7e89441d Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Wed, 26 Sep 2012 10:09:51 +0100 -Subject: [PATCH 21/37] MODSIGN: Automatically generate module signing keys if - missing - -Automatically generate keys for module signing if they're absent so that -allyesconfig doesn't break. The builder should consider generating their own -key and certificate, however, so that the keys are appropriately named. - -The private key for the module signer should be placed in signing_key.priv -(unencrypted!) and the public key in an X.509 certificate as signing_key.x509. - -If a transient key is desired for signing the modules, a config file for -'openssl req' can be placed in x509.genkey, looking something like the -following: - - [ req ] - default_bits = 4096 - distinguished_name = req_distinguished_name - prompt = no - x509_extensions = myexts - - [ req_distinguished_name ] - O = Magarathea - CN = Glacier signing key - emailAddress = slartibartfast@magrathea.h2g2 - - [ myexts ] - basicConstraints=critical,CA:FALSE - keyUsage=digitalSignature - subjectKeyIdentifier=hash - authorityKeyIdentifier=hash - -The build process will use this to configure: - - openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ - -x509 -config x509.genkey \ - -outform DER -out signing_key.x509 \ - -keyout signing_key.priv - -to generate the key. - -Note that it is required that the X.509 certificate have a subjectKeyIdentifier -and an authorityKeyIdentifier. Without those, the certificate will be -rejected. These can be used to check the validity of a certificate. - -Note that 'make distclean' will remove signing_key.{priv,x509} and x509.genkey, -whether or not they were generated automatically. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - kernel/Makefile | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 49 insertions(+) - -diff --git a/kernel/Makefile b/kernel/Makefile -index 08ba8a6..58c6f11 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -132,3 +132,52 @@ quiet_cmd_timeconst = TIMEC $@ - targets += timeconst.h - $(obj)/timeconst.h: $(src)/timeconst.pl FORCE - $(call if_changed,timeconst) -+ -+ifeq ($(CONFIG_MODULE_SIG),y) -+ -+############################################################################### -+# -+# If module signing is requested, say by allyesconfig, but a key has not been -+# supplied, then one will need to be generated to make sure the build does not -+# fail and that the kernel may be used afterwards. -+# -+############################################################################### -+signing_key.priv signing_key.x509: x509.genkey -+ @echo "###" -+ @echo "### Now generating an X.509 key pair to be used for signing modules." -+ @echo "###" -+ @echo "### If this takes a long time, you might wish to run rngd in the" -+ @echo "### background to keep the supply of entropy topped up. It" -+ @echo "### needs to be run as root, and should use a hardware random" -+ @echo "### number generator if one is available, eg:" -+ @echo "###" -+ @echo "### rngd -r /dev/hwrandom" -+ @echo "###" -+ openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ -+ -x509 -config x509.genkey \ -+ -outform DER -out signing_key.x509 \ -+ -keyout signing_key.priv -+ @echo "###" -+ @echo "### Key pair generated." -+ @echo "###" -+ -+x509.genkey: -+ @echo Generating X.509 key generation config -+ @echo >x509.genkey "[ req ]" -+ @echo >>x509.genkey "default_bits = 4096" -+ @echo >>x509.genkey "distinguished_name = req_distinguished_name" -+ @echo >>x509.genkey "prompt = no" -+ @echo >>x509.genkey "x509_extensions = myexts" -+ @echo >>x509.genkey -+ @echo >>x509.genkey "[ req_distinguished_name ]" -+ @echo >>x509.genkey "O = Magrathea" -+ @echo >>x509.genkey "CN = Glacier signing key" -+ @echo >>x509.genkey "emailAddress = slartibartfast@magrathea.h2g2" -+ @echo >>x509.genkey -+ @echo >>x509.genkey "[ myexts ]" -+ @echo >>x509.genkey "basicConstraints=critical,CA:FALSE" -+ @echo >>x509.genkey "keyUsage=digitalSignature" -+ @echo >>x509.genkey "subjectKeyIdentifier=hash" -+ @echo >>x509.genkey "authorityKeyIdentifier=keyid" -+endif -+CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey --- -1.7.12.1 - - -From 51da59e56f0666efe97c376830dffefdfcecd21f Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Wed, 26 Sep 2012 10:09:51 +0100 -Subject: [PATCH 22/37] MODSIGN: Provide module signing public keys to the - kernel - -Include a PGP keyring containing the public keys required to perform module -verification in the kernel image during build and create a special keyring -during boot which is then populated with keys of crypto type holding the public -keys found in the PGP keyring. - -These can be seen by root: - -[root@andromeda ~]# cat /proc/keys -07ad4ee0 I----- 1 perm 3f010000 0 0 crypto modsign.0: RSA 87b9b3bd [] -15c7f8c3 I----- 1 perm 1f030000 0 0 keyring .module_sign: 1/4 -... - -It is probably worth permitting root to invalidate these keys, resulting in -their removal and preventing further modules from being loaded with that key. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - kernel/Makefile | 11 ++++- - kernel/modsign_pubkey.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++ - kernel/module-internal.h | 2 + - 3 files changed, 124 insertions(+), 2 deletions(-) - create mode 100644 kernel/modsign_pubkey.c - -diff --git a/kernel/Makefile b/kernel/Makefile -index 58c6f11..111a845 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -55,7 +55,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o - obj-$(CONFIG_PROVE_LOCKING) += spinlock.o - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += module.o --obj-$(CONFIG_MODULE_SIG) += module_signing.o -+obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -@@ -134,6 +134,13 @@ $(obj)/timeconst.h: $(src)/timeconst.pl FORCE - $(call if_changed,timeconst) - - ifeq ($(CONFIG_MODULE_SIG),y) -+# -+# Pull the signing certificate and any extra certificates into the kernel -+# -+extra_certificates: -+ touch $@ -+ -+kernel/modsign_pubkey.o: signing_key.x509 extra_certificates - - ############################################################################### - # -@@ -180,4 +187,4 @@ x509.genkey: - @echo >>x509.genkey "subjectKeyIdentifier=hash" - @echo >>x509.genkey "authorityKeyIdentifier=keyid" - endif --CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey -+CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey extra_certificates -diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c -new file mode 100644 -index 0000000..4646eb2 ---- /dev/null -+++ b/kernel/modsign_pubkey.c -@@ -0,0 +1,113 @@ -+/* Public keys for module signature verification -+ * -+ * Copyright (C) 2012 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. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/cred.h> -+#include <linux/err.h> -+#include <keys/asymmetric-type.h> -+#include "module-internal.h" -+ -+struct key *modsign_keyring; -+ -+extern __initdata const u8 modsign_certificate_list[]; -+extern __initdata const u8 modsign_certificate_list_end[]; -+asm(".section .init.data,\"aw\"\n" -+ "modsign_certificate_list:\n" -+ ".incbin \"signing_key.x509\"\n" -+ ".incbin \"extra_certificates\"\n" -+ "modsign_certificate_list_end:" -+ ); -+ -+/* -+ * We need to make sure ccache doesn't cache the .o file as it doesn't notice -+ * if modsign.pub changes. -+ */ -+static __initdata const char annoy_ccache[] = __TIME__ "foo"; -+ -+/* -+ * Load the compiled-in keys -+ */ -+static __init int module_verify_init(void) -+{ -+ pr_notice("Initialise module verification\n"); -+ -+ modsign_keyring = key_alloc(&key_type_keyring, ".module_sign", -+ KUIDT_INIT(0), KGIDT_INIT(0), -+ current_cred(), -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW | KEY_USR_READ, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ if (IS_ERR(modsign_keyring)) -+ panic("Can't allocate module signing keyring\n"); -+ -+ if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) -+ panic("Can't instantiate module signing keyring\n"); -+ -+ return 0; -+} -+ -+/* -+ * Must be initialised before we try and load the keys into the keyring. -+ */ -+device_initcall(module_verify_init); -+ -+/* -+ * Load the compiled-in keys -+ */ -+static __init int load_module_signing_keys(void) -+{ -+ key_ref_t key; -+ const u8 *p, *end; -+ size_t plen; -+ -+ pr_notice("Loading module verification certificates\n"); -+ -+ end = modsign_certificate_list_end; -+ p = modsign_certificate_list; -+ while (p < end) { -+ /* Each cert begins with an ASN.1 SEQUENCE tag and must be more -+ * than 256 bytes in size. -+ */ -+ if (end - p < 4) -+ goto dodgy_cert; -+ if (p[0] != 0x30 && -+ p[1] != 0x82) -+ goto dodgy_cert; -+ plen = (p[2] << 8) | p[3]; -+ plen += 4; -+ if (plen > end - p) -+ goto dodgy_cert; -+ -+ key = key_create_or_update(make_key_ref(modsign_keyring, 1), -+ "asymmetric", -+ NULL, -+ p, -+ plen, -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ if (IS_ERR(key)) -+ pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n", -+ PTR_ERR(key)); -+ else -+ pr_notice("MODSIGN: Loaded cert '%s'\n", -+ key_ref_to_ptr(key)->description); -+ p += plen; -+ } -+ -+ return 0; -+ -+dodgy_cert: -+ pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n"); -+ return 0; -+} -+late_initcall(load_module_signing_keys); -diff --git a/kernel/module-internal.h b/kernel/module-internal.h -index 033c17f..6114a13 100644 ---- a/kernel/module-internal.h -+++ b/kernel/module-internal.h -@@ -9,5 +9,7 @@ - * 2 of the Licence, or (at your option) any later version. - */ - -+extern struct key *modsign_keyring; -+ - extern int mod_verify_sig(const void *mod, unsigned long modlen, - const void *sig, unsigned long siglen); --- -1.7.12.1 - - -From 81a8def438b252dac4aa9c7eda39ad517bfe51ac Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Wed, 26 Sep 2012 10:11:03 +0100 -Subject: [PATCH 23/37] MODSIGN: Implement module signature checking - -Check the signature on the module against the keys compiled into the kernel or -available in a hardware key store. - -Currently, only RSA keys are supported - though that's easy enough to change, -and the signature is expected to contain raw components (so not a PGP or -PKCS#7 formatted blob). - -The signature blob is expected to consist of the following pieces in order: - - (1) The binary identifier for the key. This is expected to match the - SubjectKeyIdentifier from an X.509 certificate. Only X.509 type - identifiers are currently supported. - - (2) The signature data, consisting of a series of MPIs in which each is in - the format of a 2-byte BE word sizes followed by the content data. - - (3) A 12 byte information block of the form: - - struct module_signature { - enum pkey_algo algo : 8; - enum pkey_hash_algo hash : 8; - enum pkey_id_type id_type : 8; - u8 __pad; - __be32 id_length; - __be32 sig_length; - }; - - The three enums are defined in crypto/public_key.h. - - 'algo' contains the public-key algorithm identifier (0->DSA, 1->RSA). - - 'hash' contains the digest algorithm identifier (0->MD4, 1->MD5, 2->SHA1, - etc.). - - 'id_type' contains the public-key identifier type (0->PGP, 1->X.509). - - '__pad' should be 0. - - 'id_length' should contain in the binary identifier length in BE form. - - 'sig_length' should contain in the signature data length in BE form. - - The lengths are in BE order rather than CPU order to make dealing with - cross-compilation easier. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (minor Kconfig fix) ---- - init/Kconfig | 8 ++ - kernel/module_signing.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 229 insertions(+), 1 deletion(-) - -diff --git a/init/Kconfig b/init/Kconfig -index 00d4579..abc6e63 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1588,6 +1588,14 @@ config MODULE_SRCVERSION_ALL - config MODULE_SIG - bool "Module signature verification" - depends on MODULES -+ select KEYS -+ select CRYPTO -+ select ASYMMETRIC_KEY_TYPE -+ select ASYMMETRIC_PUBLIC_KEY_SUBTYPE -+ select PUBLIC_KEY_ALGO_RSA -+ select ASN1 -+ select OID_REGISTRY -+ select X509_CERTIFICATE_PARSER - help - Check modules for valid signatures upon load: the signature - is simply appended to the module. For more information see -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index 499728a..6b09f69 100644 ---- a/kernel/module_signing.c -+++ b/kernel/module_signing.c -@@ -11,13 +11,233 @@ - - #include <linux/kernel.h> - #include <linux/err.h> -+#include <crypto/public_key.h> -+#include <crypto/hash.h> -+#include <keys/asymmetric-type.h> - #include "module-internal.h" - - /* -+ * Module signature information block. -+ * -+ * The constituents of the signature section are, in order: -+ * -+ * - Signer's name -+ * - Key identifier -+ * - Signature data -+ * - Information block -+ */ -+struct module_signature { -+ enum pkey_algo algo : 8; /* Public-key crypto algorithm */ -+ enum pkey_hash_algo hash : 8; /* Digest algorithm */ -+ enum pkey_id_type id_type : 8; /* Key identifier type */ -+ u8 signer_len; /* Length of signer's name */ -+ u8 key_id_len; /* Length of key identifier */ -+ u8 __pad[3]; -+ __be32 sig_len; /* Length of signature data */ -+}; -+ -+/* -+ * Digest the module contents. -+ */ -+static struct public_key_signature *mod_make_digest(enum pkey_hash_algo hash, -+ const void *mod, -+ unsigned long modlen) -+{ -+ struct public_key_signature *pks; -+ struct crypto_shash *tfm; -+ struct shash_desc *desc; -+ size_t digest_size, desc_size; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ /* Allocate the hashing algorithm we're going to need and find out how -+ * big the hash operational data will be. -+ */ -+ tfm = crypto_alloc_shash(pkey_hash_algo[hash], 0, 0); -+ if (IS_ERR(tfm)) -+ return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm); -+ -+ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); -+ digest_size = crypto_shash_digestsize(tfm); -+ -+ /* We allocate the hash operational data storage on the end of our -+ * context data and the digest output buffer on the end of that. -+ */ -+ ret = -ENOMEM; -+ pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL); -+ if (!pks) -+ goto error_no_pks; -+ -+ pks->pkey_hash_algo = hash; -+ pks->digest = (u8 *)pks + sizeof(*pks) + desc_size; -+ pks->digest_size = digest_size; -+ -+ desc = (void *)pks + sizeof(*pks); -+ desc->tfm = tfm; -+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; -+ -+ ret = crypto_shash_init(desc); -+ if (ret < 0) -+ goto error; -+ -+ ret = crypto_shash_finup(desc, mod, modlen, pks->digest); -+ if (ret < 0) -+ goto error; -+ -+ crypto_free_shash(tfm); -+ pr_devel("<==%s() = ok\n", __func__); -+ return pks; -+ -+error: -+ kfree(pks); -+error_no_pks: -+ crypto_free_shash(tfm); -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ERR_PTR(ret); -+} -+ -+/* -+ * Extract an MPI array from the signature data. This represents the actual -+ * signature. Each raw MPI is prefaced by a BE 2-byte value indicating the -+ * size of the MPI in bytes. -+ * -+ * RSA signatures only have one MPI, so currently we only read one. -+ */ -+static int mod_extract_mpi_array(struct public_key_signature *pks, -+ const void *data, size_t len) -+{ -+ size_t nbytes; -+ MPI mpi; -+ -+ if (len < 3) -+ return -EBADMSG; -+ nbytes = ((const u8 *)data)[0] << 8 | ((const u8 *)data)[1]; -+ data += 2; -+ len -= 2; -+ if (len != nbytes) -+ return -EBADMSG; -+ -+ mpi = mpi_read_raw_data(data, nbytes); -+ if (!mpi) -+ return -ENOMEM; -+ pks->mpi[0] = mpi; -+ pks->nr_mpi = 1; -+ return 0; -+} -+ -+/* -+ * Request an asymmetric key. -+ */ -+static struct key *request_asymmetric_key(const char *signer, size_t signer_len, -+ const u8 *key_id, size_t key_id_len) -+{ -+ key_ref_t key; -+ size_t i; -+ char *id, *q; -+ -+ pr_devel("==>%s(,%zu,,%zu)\n", __func__, signer_len, key_id_len); -+ -+ /* Construct an identifier. */ -+ id = kmalloc(signer_len + 2 + key_id_len * 2 + 1, GFP_KERNEL); -+ if (!id) -+ return ERR_PTR(-ENOKEY); -+ -+ memcpy(id, signer, signer_len); -+ -+ q = id + signer_len; -+ *q++ = ':'; -+ *q++ = ' '; -+ for (i = 0; i < key_id_len; i++) { -+ *q++ = hex_asc[*key_id >> 4]; -+ *q++ = hex_asc[*key_id++ & 0x0f]; -+ } -+ -+ *q = 0; -+ -+ pr_debug("Look up: \"%s\"\n", id); -+ -+ key = keyring_search(make_key_ref(modsign_keyring, 1), -+ &key_type_asymmetric, id); -+ if (IS_ERR(key)) -+ pr_warn("Request for unknown module key '%s' err %ld\n", -+ id, PTR_ERR(key)); -+ kfree(id); -+ -+ if (IS_ERR(key)) { -+ switch (PTR_ERR(key)) { -+ /* Hide some search errors */ -+ case -EACCES: -+ case -ENOTDIR: -+ case -EAGAIN: -+ return ERR_PTR(-ENOKEY); -+ default: -+ return ERR_CAST(key); -+ } -+ } -+ -+ pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key))); -+ return key_ref_to_ptr(key); -+} -+ -+/* - * Verify the signature on a module. - */ - int mod_verify_sig(const void *mod, unsigned long modlen, - const void *sig, unsigned long siglen) - { -- return -ENOKEY; -+ struct public_key_signature *pks; -+ struct module_signature ms; -+ struct key *key; -+ size_t sig_len; -+ int ret; -+ -+ pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen); -+ -+ if (siglen <= sizeof(ms)) -+ return -EBADMSG; -+ -+ memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms)); -+ siglen -= sizeof(ms); -+ -+ sig_len = be32_to_cpu(ms.sig_len); -+ if (sig_len >= siglen || -+ siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len) -+ return -EBADMSG; -+ -+ /* For the moment, only support RSA and X.509 identifiers */ -+ if (ms.algo != PKEY_ALGO_RSA || -+ ms.id_type != PKEY_ID_X509) -+ return -ENOPKG; -+ -+ if (ms.hash >= PKEY_HASH__LAST || -+ !pkey_hash_algo[ms.hash]) -+ return -ENOPKG; -+ -+ key = request_asymmetric_key(sig, ms.signer_len, -+ sig + ms.signer_len, ms.key_id_len); -+ if (IS_ERR(key)) -+ return PTR_ERR(key); -+ -+ pks = mod_make_digest(ms.hash, mod, modlen); -+ if (IS_ERR(pks)) { -+ ret = PTR_ERR(pks); -+ goto error_put_key; -+ } -+ -+ ret = mod_extract_mpi_array(pks, sig + ms.signer_len + ms.key_id_len, -+ sig_len); -+ if (ret < 0) -+ goto error_free_pks; -+ -+ ret = verify_signature(key, pks); -+ pr_devel("verify_signature() = %d\n", ret); -+ -+error_free_pks: -+ mpi_free(pks->rsa.s); -+ kfree(pks); -+error_put_key: -+ key_put(key); -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; - } --- -1.7.12.1 - - -From 952f5922dd45a25f7896843df02aec2250c41f42 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Wed, 26 Sep 2012 10:11:06 +0100 -Subject: [PATCH 24/37] MODSIGN: Provide a script for generating a key ID from - an X.509 cert - -Provide a script to parse an X.509 certificate and certain pieces of -information from it in order to generate a key identifier to be included within -a module signature. - -The script takes the Subject Name and extracts (if present) the -organizationName (O), the commonName (CN) and the emailAddress and fabricates -the signer's name from them: - - (1) If both O and CN exist, then the name will be "O: CN", unless: - - (a) CN is prefixed by O, in which case only CN is used. - - (b) CN and O share at least the first 7 characters, in which case only CN - is used. - - (2) Otherwise, CN is used if present. - - (3) Otherwise, O is used if present. - - (4) Otherwise the emailAddress is used, if present. - - (5) Otherwise a blank name is used. - -The script emits a binary encoded identifier in the following form: - - - 2 BE bytes indicating the length of the signer's name. - - - 2 BE bytes indicating the length of the subject key identifier. - - - The characters of the signer's name. - - - The bytes of the subject key identifier. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - scripts/x509keyid | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 268 insertions(+) - create mode 100755 scripts/x509keyid - -diff --git a/scripts/x509keyid b/scripts/x509keyid -new file mode 100755 -index 0000000..c8e91a4 ---- /dev/null -+++ b/scripts/x509keyid -@@ -0,0 +1,268 @@ -+#!/usr/bin/perl -w -+# -+# Generate an identifier from an X.509 certificate that can be placed in a -+# module signature to indentify the key to use. -+# -+# Format: -+# -+# ./scripts/x509keyid <x509-cert> <signer's-name> <key-id> -+# -+# We read the DER-encoded X509 certificate and parse it to extract the Subject -+# name and Subject Key Identifier. The provide the data we need to build the -+# certificate identifier. -+# -+# The signer's name part of the identifier is fabricated from the commonName, -+# the organizationName or the emailAddress components of the X.509 subject -+# name and written to the second named file. -+# -+# The subject key ID to select which of that signer's certificates we're -+# intending to use to sign the module is written to the third named file. -+# -+use strict; -+ -+my $raw_data; -+ -+die "Need three filenames\n" if ($#ARGV != 2); -+ -+my $src = $ARGV[0]; -+ -+open(FD, "<$src") || die $src; -+binmode FD; -+my @st = stat(FD); -+die $src if (!@st); -+read(FD, $raw_data, $st[7]) || die $src; -+close(FD); -+ -+my $UNIV = 0 << 6; -+my $APPL = 1 << 6; -+my $CONT = 2 << 6; -+my $PRIV = 3 << 6; -+ -+my $CONS = 0x20; -+ -+my $BOOLEAN = 0x01; -+my $INTEGER = 0x02; -+my $BIT_STRING = 0x03; -+my $OCTET_STRING = 0x04; -+my $NULL = 0x05; -+my $OBJ_ID = 0x06; -+my $UTF8String = 0x0c; -+my $SEQUENCE = 0x10; -+my $SET = 0x11; -+my $UTCTime = 0x17; -+my $GeneralizedTime = 0x18; -+ -+my %OIDs = ( -+ pack("CCC", 85, 4, 3) => "commonName", -+ pack("CCC", 85, 4, 6) => "countryName", -+ pack("CCC", 85, 4, 10) => "organizationName", -+ pack("CCC", 85, 4, 11) => "organizationUnitName", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", -+ pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", -+ pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", -+ pack("CCC", 85, 29, 19) => "basicConstraints" -+); -+ -+############################################################################### -+# -+# Extract an ASN.1 element from a string and return information about it. -+# -+############################################################################### -+sub asn1_extract($$@) -+{ -+ my ($cursor, $expected_tag, $optional) = @_; -+ -+ return [ -1 ] -+ if ($cursor->[1] == 0 && $optional); -+ -+ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" -+ if ($cursor->[1] < 2); -+ -+ my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); -+ -+ if ($expected_tag != -1 && $tag != $expected_tag) { -+ return [ -1 ] -+ if ($optional); -+ die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, -+ " not ", $expected_tag, ")\n"; -+ } -+ -+ $cursor->[0] += 2; -+ $cursor->[1] -= 2; -+ -+ die $src, ": ", $cursor->[0], ": ASN.1 long tag\n" -+ if (($tag & 0x1f) == 0x1f); -+ die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n" -+ if ($len == 0x80); -+ -+ if ($len > 0x80) { -+ my $l = $len - 0x80; -+ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" -+ if ($cursor->[1] < $l); -+ -+ if ($l == 0x1) { -+ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); -+ } elsif ($l = 0x2) { -+ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); -+ } elsif ($l = 0x3) { -+ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; -+ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); -+ } elsif ($l = 0x4) { -+ $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); -+ } else { -+ die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; -+ } -+ -+ $cursor->[0] += $l; -+ $cursor->[1] -= $l; -+ } -+ -+ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" -+ if ($cursor->[1] < $len); -+ -+ my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; -+ $cursor->[0] += $len; -+ $cursor->[1] -= $len; -+ -+ return $ret; -+} -+ -+############################################################################### -+# -+# Retrieve the data referred to by a cursor -+# -+############################################################################### -+sub asn1_retrieve($) -+{ -+ my ($cursor) = @_; -+ my ($offset, $len, $data) = @$cursor; -+ return substr($$data, $offset, $len); -+} -+ -+############################################################################### -+# -+# Roughly parse the X.509 certificate -+# -+############################################################################### -+my $cursor = [ 0, length($raw_data), \$raw_data ]; -+ -+my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); -+my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); -+my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); -+my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); -+my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); -+my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); -+my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); -+ -+my $subject_key_id = (); -+my $authority_key_id = (); -+ -+# -+# Parse the extension list -+# -+if ($extension_list->[0] != -1) { -+ my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); -+ -+ while ($extensions->[1]->[1] > 0) { -+ my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); -+ my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); -+ my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); -+ my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); -+ -+ my $raw_oid = asn1_retrieve($x_oid->[1]); -+ next if (!exists($OIDs{$raw_oid})); -+ my $x_type = $OIDs{$raw_oid}; -+ -+ my $raw_value = asn1_retrieve($x_val->[1]); -+ -+ if ($x_type eq "subjectKeyIdentifier") { -+ my $vcursor = [ 0, length($raw_value), \$raw_value ]; -+ -+ $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); -+ } -+ } -+} -+ -+############################################################################### -+# -+# Determine what we're going to use as the signer's name. In order of -+# preference, take one of: commonName, organizationName or emailAddress. -+# -+############################################################################### -+my $org = ""; -+my $cn = ""; -+my $email = ""; -+ -+while ($subject->[1]->[1] > 0) { -+ my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); -+ my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); -+ my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); -+ my $n_val = asn1_extract($attr->[1], -1); -+ -+ my $raw_oid = asn1_retrieve($n_oid->[1]); -+ next if (!exists($OIDs{$raw_oid})); -+ my $n_type = $OIDs{$raw_oid}; -+ -+ my $raw_value = asn1_retrieve($n_val->[1]); -+ -+ if ($n_type eq "organizationName") { -+ $org = $raw_value; -+ } elsif ($n_type eq "commonName") { -+ $cn = $raw_value; -+ } elsif ($n_type eq "emailAddress") { -+ $email = $raw_value; -+ } -+} -+ -+my $id_name = $email; -+ -+if ($org && $cn) { -+ # Don't use the organizationName if the commonName repeats it -+ if (length($org) <= length($cn) && -+ substr($cn, 0, length($org)) eq $org) { -+ $id_name = $cn; -+ goto got_id_name; -+ } -+ -+ # Or a signifcant chunk of it -+ if (length($org) >= 7 && -+ length($cn) >= 7 && -+ substr($cn, 0, 7) eq substr($org, 0, 7)) { -+ $id_name = $cn; -+ goto got_id_name; -+ } -+ -+ $id_name = $org . ": " . $cn; -+} elsif ($org) { -+ $id_name = $org; -+} elsif ($cn) { -+ $id_name = $cn; -+} -+ -+got_id_name: -+ -+############################################################################### -+# -+# Output the signer's name and the key identifier that we're going to include -+# in module signatures. -+# -+############################################################################### -+die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" -+ if (!$subject_key_id); -+ -+my $id_key_id = asn1_retrieve($subject_key_id->[1]); -+ -+open(OUTFD, ">$ARGV[1]") || die $ARGV[1]; -+print OUTFD $id_name; -+close OUTFD || die $ARGV[1]; -+ -+open(OUTFD, ">$ARGV[2]") || die $ARGV[2]; -+print OUTFD $id_key_id; -+close OUTFD || die $ARGV[2]; --- -1.7.12.1 - - -From 52a1f2ba9612d689f1a5ed6c1a03bd784f34bf1c Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Wed, 26 Sep 2012 10:11:06 +0100 -Subject: [PATCH 25/37] MODSIGN: Sign modules during the build process - -If CONFIG_MODULE_SIG is set, then this patch will cause all modules files to -to have signatures added. The following steps will occur: - - (1) The module will be linked to foo.ko.unsigned instead of foo.ko - - (2) The module will be stripped using both "strip -x -g" and "eu-strip" to - ensure minimal size for inclusion in an initramfs. - - (3) The signature will be generated on the stripped module. - - (4) The signature will be appended to the module, along with some information - about the signature and a magic string that indicates the presence of the - signature. - -Step (3) requires private and public keys to be available. By default these -are expected to be found in files: - - signing_key.priv - signing_key.x509 - -in the base directory of the build. The first is the private key in PEM form -and the second is the X.509 certificate in DER form as can be generated from -openssl: - - openssl req \ - -new -x509 -outform PEM -out signing_key.x509 \ - -keyout signing_key.priv -nodes \ - -subj "/CN=H2G2/O=Magrathea/CN=Slartibartfast" - -If the secret key is not found then signing will be skipped and the unsigned -module from (1) will just be copied to foo.ko. - -If signing occurs, lines like the following will be seen: - - LD [M] fs/foo/foo.ko.unsigned - STRIP [M] fs/foo/foo.ko.stripped - SIGN [M] fs/foo/foo.ko - -will appear in the build log. If the signature step will be skipped and the -following will be seen: - - LD [M] fs/foo/foo.ko.unsigned - STRIP [M] fs/foo/foo.ko.stripped - NO SIGN [M] fs/foo/foo.ko - -NOTE! After the signature step, the signed module _must_not_ be passed through -strip. The unstripped, unsigned module is still available at the name on the -LD [M] line. This restriction may affect packaging tools (such as rpmbuild) -and initramfs composition tools. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - scripts/Makefile.modpost | 77 ++++++++++++++++++++++++++++++- - scripts/sign-file | 115 +++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 191 insertions(+), 1 deletion(-) - create mode 100644 scripts/sign-file - -diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost -index 08dce14..2a4d1a1 100644 ---- a/scripts/Makefile.modpost -+++ b/scripts/Makefile.modpost -@@ -14,7 +14,8 @@ - # 3) create one <module>.mod.c file pr. module - # 4) create one Module.symvers file with CRC for all exported symbols - # 5) compile all <module>.mod.c files --# 6) final link of the module to a <module.ko> file -+# 6) final link of the module to a <module.ko> (or <module.unsigned>) file -+# 7) signs the modules to a <module.ko> file - - # Step 3 is used to place certain information in the module's ELF - # section, including information such as: -@@ -32,6 +33,8 @@ - # Step 4 is solely used to allow module versioning in external modules, - # where the CRC of each module is retrieved from the Module.symvers file. - -+# Step 7 is dependent on CONFIG_MODULE_SIG being enabled. -+ - # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined - # symbols in the final module linking stage - # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. -@@ -116,6 +119,7 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE - targets += $(modules:.ko=.mod.o) - - # Step 6), final link of the modules -+ifneq ($(CONFIG_MODULE_SIG),y) - quiet_cmd_ld_ko_o = LD [M] $@ - cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ - $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ -@@ -125,7 +129,78 @@ $(modules): %.ko :%.o %.mod.o FORCE - $(call if_changed,ld_ko_o) - - targets += $(modules) -+else -+quiet_cmd_ld_ko_unsigned_o = LD [M] $@ -+ cmd_ld_ko_unsigned_o = \ -+ $(LD) -r $(LDFLAGS) \ -+ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ -+ -o $@ $(filter-out FORCE,$^) \ -+ $(if $(AFTER_LINK),; $(AFTER_LINK)) -+ -+$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE -+ $(call if_changed,ld_ko_unsigned_o) -+ -+targets += $(modules:.ko=.ko.unsigned) -+ -+# Step 7), sign the modules -+MODSECKEY = ./signing_key.priv -+MODPUBKEY = ./signing_key.x509 -+ -+ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY)) -+ifeq ($(KBUILD_SRC),) -+ # no O= is being used -+ SCRIPTS_DIR := scripts -+else -+ SCRIPTS_DIR := $(KBUILD_SRC)/scripts -+endif -+SIGN_MODULES := 1 -+else -+SIGN_MODULES := 0 -+endif -+ -+# only sign if it's an in-tree module -+ifneq ($(KBUILD_EXTMOD),) -+SIGN_MODULES := 0 -+endif - -+# We strip the module as best we can - note that using both strip and eu-strip -+# results in a smaller module than using either alone. -+EU_STRIP = $(shell which eu-strip || echo true) -+ -+quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@ -+ cmd_sign_ko_stripped_ko_unsigned = \ -+ cp $< $@ && \ -+ strip -x -g $@ && \ -+ $(EU_STRIP) $@ -+ -+ifeq ($(SIGN_MODULES),1) -+ -+quiet_cmd_genkeyid = GENKEYID $@ -+ cmd_genkeyid = \ -+ perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid -+ -+%.signer %.keyid: % -+ $(call if_changed,genkeyid) -+ -+KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid -+quiet_cmd_sign_ko_ko_stripped = SIGN [M] $@ -+ cmd_sign_ko_ko_stripped = \ -+ sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) $< $@ -+else -+KEYRING_DEP := -+quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@ -+ cmd_sign_ko_ko_unsigned = \ -+ cp $< $@ -+endif -+ -+$(modules): %.ko :%.ko.stripped $(KEYRING_DEP) FORCE -+ $(call if_changed,sign_ko_ko_stripped) -+ -+$(patsubst %.ko,%.ko.stripped,$(modules)): %.ko.stripped :%.ko.unsigned FORCE -+ $(call if_changed,sign_ko_stripped_ko_unsigned) -+ -+targets += $(modules) -+endif - - # Add FORCE to the prequisites of a target to force it to be always rebuilt. - # --------------------------------------------------------------------------- -diff --git a/scripts/sign-file b/scripts/sign-file -new file mode 100644 -index 0000000..e58e34e ---- /dev/null -+++ b/scripts/sign-file -@@ -0,0 +1,115 @@ -+#!/bin/sh -+# -+# Sign a module file using the given key. -+# -+# Format: sign-file <key> <x509> <src-file> <dst-file> -+# -+ -+scripts=`dirname $0` -+ -+CONFIG_MODULE_SIG_SHA512=y -+if [ -r .config ] -+then -+ . ./.config -+fi -+ -+key="$1" -+x509="$2" -+src="$3" -+dst="$4" -+ -+if [ ! -r "$key" ] -+then -+ echo "Can't read private key" >&2 -+ exit 2 -+fi -+ -+if [ ! -r "$x509" ] -+then -+ echo "Can't read X.509 certificate" >&2 -+ exit 2 -+fi -+if [ ! -r "$x509.signer" ] -+then -+ echo "Can't read Signer name" >&2 -+ exit 2; -+fi -+if [ ! -r "$x509.keyid" ] -+then -+ echo "Can't read Key identifier" >&2 -+ exit 2; -+fi -+ -+# -+# Signature parameters -+# -+algo=1 # Public-key crypto algorithm: RSA -+hash= # Digest algorithm -+id_type=1 # Identifier type: X.509 -+ -+# -+# Digest the data -+# -+dgst= -+if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ] -+then -+ prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14" -+ dgst=-sha1 -+ hash=2 -+elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ] -+then -+ prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C" -+ dgst=-sha224 -+ hash=7 -+elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ] -+then -+ prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20" -+ dgst=-sha256 -+ hash=4 -+elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ] -+then -+ prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30" -+ dgst=-sha384 -+ hash=5 -+elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ] -+then -+ prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40" -+ dgst=-sha512 -+ hash=6 -+else -+ echo "$0: Can't determine hash algorithm" >&2 -+ exit 2 -+fi -+ -+( -+perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? -+openssl dgst $dgst -binary $src || exit $? -+) >$src.dig || exit $? -+ -+# -+# Generate the binary signature, which will be just the integer that comprises -+# the signature with no metadata attached. -+# -+openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $? -+signerlen=`stat -c %s $x509.signer` -+keyidlen=`stat -c %s $x509.keyid` -+siglen=`stat -c %s $src.sig` -+ -+# -+# Build the signed binary -+# -+( -+ cat $src || exit $? -+ echo '~Module signature appended~' || exit $? -+ cat $x509.signer $x509.keyid || exit $? -+ -+ # Preface each signature integer with a 2-byte BE length -+ perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? -+ cat $src.sig || exit $? -+ -+ # Generate the information block -+ perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? -+) >$dst~ || exit $? -+ -+# Permit in-place signing -+mv $dst~ $dst || exit $? --- -1.7.12.1 - - -From 1e9ce85a6c40e2c0ba6c589605ceb565b1c83784 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 28 Sep 2012 11:16:57 +0100 -Subject: [PATCH 26/37] MODSIGN: Use the same digest for the autogen key sig - as for the module sig - -Use the same digest type for the autogenerated key signature as for the module -signature so that the hash algorithm is guaranteed to be present in the kernel. - -Without this, the X.509 certificate loader may reject the X.509 certificate so -generated because it was self-signed and the signature will be checked against -itself - but this won't work if the digest algorithm must be loaded as a -module. - -The symptom is that the key fails to load with the following message emitted -into the kernel log: - - MODSIGN: Problem loading in-kernel X.509 certificate (-65) - -the error in brackets being -ENOPKG. What you should see is something like: - - MODSIGN: Loaded cert 'Magarathea: Glacier signing key: 9588321144239a119d3406d4c4cf1fbae1836fa0' - -Note that this doesn't apply to certificates that are not self-signed as we -don't check those currently as they require the parent CA certificate to be -available. - -Reported-by: Rusty Russell <rusty@rustcorp.com.au> -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - kernel/Makefile | 22 +++++++++++++++++++++- - 1 file changed, 21 insertions(+), 1 deletion(-) - -diff --git a/kernel/Makefile b/kernel/Makefile -index 111a845..a799029 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -149,6 +149,26 @@ kernel/modsign_pubkey.o: signing_key.x509 extra_certificates - # fail and that the kernel may be used afterwards. - # - ############################################################################### -+sign_key_with_hash := -+ifeq ($(CONFIG_MODULE_SIG_SHA1),y) -+sign_key_with_hash := -sha1 -+endif -+ifeq ($(CONFIG_MODULE_SIG_SHA224),y) -+sign_key_with_hash := -sha224 -+endif -+ifeq ($(CONFIG_MODULE_SIG_SHA256),y) -+sign_key_with_hash := -sha256 -+endif -+ifeq ($(CONFIG_MODULE_SIG_SHA384),y) -+sign_key_with_hash := -sha384 -+endif -+ifeq ($(CONFIG_MODULE_SIG_SHA512),y) -+sign_key_with_hash := -sha512 -+endif -+ifeq ($(sign_key_with_hash),) -+$(error Could not determine digest type to use from kernel config) -+endif -+ - signing_key.priv signing_key.x509: x509.genkey - @echo "###" - @echo "### Now generating an X.509 key pair to be used for signing modules." -@@ -160,7 +180,7 @@ signing_key.priv signing_key.x509: x509.genkey - @echo "###" - @echo "### rngd -r /dev/hwrandom" - @echo "###" -- openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ -+ openssl req -new -nodes -utf8 $(sign_key_with_hash) -days 36500 -batch \ - -x509 -config x509.genkey \ - -outform DER -out signing_key.x509 \ - -keyout signing_key.priv --- -1.7.12.1 - - -From 4c13d777ecee93ae75dae3184473003acff05a53 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 28 Sep 2012 11:16:57 +0100 -Subject: [PATCH 27/37] MODSIGN: Use utf8 strings in signer's name in - autogenerated X.509 certs - -Place an indication that the certificate should use utf8 strings into the -x509.genkey template generated by kernel/Makefile. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - kernel/Makefile | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/kernel/Makefile b/kernel/Makefile -index a799029..e951adf 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -194,6 +194,7 @@ x509.genkey: - @echo >>x509.genkey "default_bits = 4096" - @echo >>x509.genkey "distinguished_name = req_distinguished_name" - @echo >>x509.genkey "prompt = no" -+ @echo >>x509.genkey "string_mask = utf8only" - @echo >>x509.genkey "x509_extensions = myexts" - @echo >>x509.genkey - @echo >>x509.genkey "[ req_distinguished_name ]" --- -1.7.12.1 - - -From 836513a2dd15675d4ad5fefa585d1b866bec4995 Mon Sep 17 00:00:00 2001 -From: Rusty Russell <rusty@rustcorp.com.au> -Date: Tue, 2 Oct 2012 14:35:24 +0930 -Subject: [PATCH 28/37] MODSIGN: Make mrproper should remove generated files. - -It doesn't, because the clean targets don't include kernel/Makefile, and -because two files were missing from the list. - -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - Makefile | 5 ++++- - kernel/Makefile | 1 - - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/Makefile b/Makefile -index b4f9eb5..e4292ea 100644 ---- a/Makefile -+++ b/Makefile -@@ -995,7 +995,10 @@ MRPROPER_DIRS += include/config usr/include include/generated \ - arch/*/include/generated - MRPROPER_FILES += .config .config.old .version .old_version \ - include/linux/version.h \ -- Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS -+ Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \ -+ signing_key.priv signing_key.x509 x509.genkey \ -+ extra_certificates signing_key.x509.keyid \ -+ signing_key.x509.signer - - # clean - Delete most, but leave enough to build external modules - # -diff --git a/kernel/Makefile b/kernel/Makefile -index e951adf..d3611c8 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -208,4 +208,3 @@ x509.genkey: - @echo >>x509.genkey "subjectKeyIdentifier=hash" - @echo >>x509.genkey "authorityKeyIdentifier=keyid" - endif --CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey extra_certificates --- -1.7.12.1 - - -From 855c92bdf2fb006e4190650b809a6216579395d5 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Tue, 2 Oct 2012 14:36:16 +0100 -Subject: [PATCH 29/37] MODSIGN: Fix 32-bit overflow in X.509 certificate - validity date checking - -The current choice of lifetime for the autogenerated X.509 of 100 years, -putting the validTo date in 2112, causes problems on 32-bit systems where a -32-bit time_t wraps in 2106. 64-bit x86_64 systems seem to be unaffected. - -This can result in something like: - - Loading module verification certificates - X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 has expired - MODSIGN: Problem loading in-kernel X.509 certificate (-127) - -Or: - - X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 is not yet valid - MODSIGN: Problem loading in-kernel X.509 certificate (-129) - -Instead of turning the dates into time_t values and comparing, turn the system -clock and the ASN.1 dates into tm structs and compare those piecemeal instead. - -Reported-by: Rusty Russell <rusty@rustcorp.com.au> -Signed-off-by: David Howells <dhowells@redhat.com> -Acked-by: Josh Boyer <jwboyer@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - crypto/asymmetric_keys/x509_cert_parser.c | 25 +++++++++--------- - crypto/asymmetric_keys/x509_parser.h | 4 +-- - crypto/asymmetric_keys/x509_public_key.c | 42 +++++++++++++++++++++++++++---- - 3 files changed, 51 insertions(+), 20 deletions(-) - -diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c -index 8fcac94..db07e8c 100644 ---- a/crypto/asymmetric_keys/x509_cert_parser.c -+++ b/crypto/asymmetric_keys/x509_cert_parser.c -@@ -434,11 +434,10 @@ int x509_process_extension(void *context, size_t hdrlen, - /* - * Record a certificate time. - */ --static int x509_note_time(time_t *_time, size_t hdrlen, -+static int x509_note_time(struct tm *tm, size_t hdrlen, - unsigned char tag, - const unsigned char *value, size_t vlen) - { -- unsigned YY, MM, DD, hh, mm, ss; - const unsigned char *p = value; - - #define dec2bin(X) ((X) - '0') -@@ -448,30 +447,30 @@ static int x509_note_time(time_t *_time, size_t hdrlen, - /* UTCTime: YYMMDDHHMMSSZ */ - if (vlen != 13) - goto unsupported_time; -- YY = DD2bin(p); -- if (YY > 50) -- YY += 1900; -+ tm->tm_year = DD2bin(p); -+ if (tm->tm_year >= 50) -+ tm->tm_year += 1900; - else -- YY += 2000; -+ tm->tm_year += 2000; - } else if (tag == ASN1_GENTIM) { - /* GenTime: YYYYMMDDHHMMSSZ */ - if (vlen != 15) - goto unsupported_time; -- YY = DD2bin(p) * 100 + DD2bin(p); -+ tm->tm_year = DD2bin(p) * 100 + DD2bin(p); - } else { - goto unsupported_time; - } - -- MM = DD2bin(p); -- DD = DD2bin(p); -- hh = DD2bin(p); -- mm = DD2bin(p); -- ss = DD2bin(p); -+ tm->tm_year -= 1900; -+ tm->tm_mon = DD2bin(p) - 1; -+ tm->tm_mday = DD2bin(p); -+ tm->tm_hour = DD2bin(p); -+ tm->tm_min = DD2bin(p); -+ tm->tm_sec = DD2bin(p); - - if (*p != 'Z') - goto unsupported_time; - -- *_time = mktime(YY, MM, DD, hh, mm, ss); - return 0; - - unsupported_time: -diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h -index 635053f..f86dc5f 100644 ---- a/crypto/asymmetric_keys/x509_parser.h -+++ b/crypto/asymmetric_keys/x509_parser.h -@@ -18,8 +18,8 @@ struct x509_certificate { - char *subject; /* Name of certificate subject */ - char *fingerprint; /* Key fingerprint as hex */ - char *authority; /* Authority key fingerprint as hex */ -- time_t valid_from; -- time_t valid_to; -+ struct tm valid_from; -+ struct tm valid_to; - enum pkey_algo pkey_algo : 8; /* Public key algorithm */ - enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ - enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index 716917c..5ab736d 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -106,7 +106,7 @@ error_no_sig: - static int x509_key_preparse(struct key_preparsed_payload *prep) - { - struct x509_certificate *cert; -- time_t now; -+ struct tm now; - size_t srlen, sulen; - char *desc = NULL; - int ret; -@@ -118,7 +118,14 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - pr_devel("Cert Issuer: %s\n", cert->issuer); - pr_devel("Cert Subject: %s\n", cert->subject); - pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); -- pr_devel("Cert Valid: %lu - %lu\n", cert->valid_from, cert->valid_to); -+ printk("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, -+ cert->valid_from.tm_mday, cert->valid_from.tm_hour, -+ cert->valid_from.tm_min, cert->valid_from.tm_sec); -+ printk("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, -+ cert->valid_to.tm_mday, cert->valid_to.tm_hour, -+ cert->valid_to.tm_min, cert->valid_to.tm_sec); - pr_devel("Cert Signature: %s + %s\n", - pkey_algo[cert->sig_pkey_algo], - pkey_hash_algo[cert->sig_hash_algo]); -@@ -130,13 +137,38 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - goto error_free_cert; - } - -- now = CURRENT_TIME.tv_sec; -- if (now < cert->valid_from) { -+ time_to_tm(CURRENT_TIME.tv_sec, 0, &now); -+ printk("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, -+ now.tm_hour, now.tm_min, now.tm_sec); -+ if (now.tm_year < cert->valid_from.tm_year || -+ (now.tm_year == cert->valid_from.tm_year && -+ (now.tm_mon < cert->valid_from.tm_mon || -+ (now.tm_mon == cert->valid_from.tm_mon && -+ (now.tm_mday < cert->valid_from.tm_mday || -+ (now.tm_mday == cert->valid_from.tm_mday && -+ (now.tm_hour < cert->valid_from.tm_hour || -+ (now.tm_hour == cert->valid_from.tm_hour && -+ (now.tm_min < cert->valid_from.tm_min || -+ (now.tm_min == cert->valid_from.tm_min && -+ (now.tm_sec < cert->valid_from.tm_sec -+ ))))))))))) { - pr_warn("Cert %s is not yet valid\n", cert->fingerprint); - ret = -EKEYREJECTED; - goto error_free_cert; - } -- if (now >= cert->valid_to) { -+ if (now.tm_year > cert->valid_to.tm_year || -+ (now.tm_year == cert->valid_to.tm_year && -+ (now.tm_mon > cert->valid_to.tm_mon || -+ (now.tm_mon == cert->valid_to.tm_mon && -+ (now.tm_mday > cert->valid_to.tm_mday || -+ (now.tm_mday == cert->valid_to.tm_mday && -+ (now.tm_hour > cert->valid_to.tm_hour || -+ (now.tm_hour == cert->valid_to.tm_hour && -+ (now.tm_min > cert->valid_to.tm_min || -+ (now.tm_min == cert->valid_to.tm_min && -+ (now.tm_sec > cert->valid_to.tm_sec -+ ))))))))))) { - pr_warn("Cert %s has expired\n", cert->fingerprint); - ret = -EKEYEXPIRED; - goto error_free_cert; --- -1.7.12.1 - - -From f69bc56c32645bcc0b1a9ee88be662e8246398b4 Mon Sep 17 00:00:00 2001 -From: Randy Dunlap <rdunlap@xenotime.net> -Date: Wed, 3 Oct 2012 16:04:46 -0700 -Subject: [PATCH 30/37] asymmetric keys: fix printk format warning - -Fix printk format warning in x509_cert_parser.c: - -crypto/asymmetric_keys/x509_cert_parser.c: In function 'x509_note_OID': -crypto/asymmetric_keys/x509_cert_parser.c:113:3: warning: format '%zu' expects type 'size_t', but argument 2 has type 'long unsigned int' - -Builds cleanly on i386 and x86_64. - -Signed-off-by: Randy Dunlap <rdunlap@xenotime.net> -Cc: David Howells <dhowells@redhat.com> -Cc: Herbert Xu <herbert@gondor.apana.org.au> -Cc: linux-crypto@vger.kernel.org -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - crypto/asymmetric_keys/x509_cert_parser.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c -index db07e8c..7fabc4c 100644 ---- a/crypto/asymmetric_keys/x509_cert_parser.c -+++ b/crypto/asymmetric_keys/x509_cert_parser.c -@@ -110,7 +110,7 @@ int x509_note_OID(void *context, size_t hdrlen, - if (ctx->last_oid == OID__NR) { - char buffer[50]; - sprint_oid(value, vlen, buffer, sizeof(buffer)); -- pr_debug("Unknown OID: [%zu] %s\n", -+ pr_debug("Unknown OID: [%lu] %s\n", - (unsigned long)value - ctx->data, buffer); - } - return 0; --- -1.7.12.1 - - -From 81338d71c284b7d001004e4a03abfce2d2144087 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Thu, 4 Oct 2012 14:21:23 +0100 -Subject: [PATCH 31/37] X.509: Convert some printk calls to pr_devel - -Some debugging printk() calls should've been converted to pr_devel() calls. -Do that now. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - crypto/asymmetric_keys/x509_public_key.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index 5ab736d..06007f0 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -118,11 +118,11 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - pr_devel("Cert Issuer: %s\n", cert->issuer); - pr_devel("Cert Subject: %s\n", cert->subject); - pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); -- printk("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", - cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, - cert->valid_from.tm_mday, cert->valid_from.tm_hour, - cert->valid_from.tm_min, cert->valid_from.tm_sec); -- printk("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ pr_devel("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", - cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, - cert->valid_to.tm_mday, cert->valid_to.tm_hour, - cert->valid_to.tm_min, cert->valid_to.tm_sec); -@@ -138,7 +138,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - } - - time_to_tm(CURRENT_TIME.tv_sec, 0, &now); -- printk("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ pr_devel("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", - now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, - now.tm_hour, now.tm_min, now.tm_sec); - if (now.tm_year < cert->valid_from.tm_year || --- -1.7.12.1 - - -From 1054ea17fe1bf8f2087197c453626153d4649ac5 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Thu, 4 Oct 2012 14:21:23 +0100 -Subject: [PATCH 32/37] X.509: Fix indefinite length element skip error - handling - -asn1_find_indefinite_length() returns an error indicator of -1, which the -caller asn1_ber_decoder() places in a size_t (which is usually unsigned) and -then checks to see whether it is less than 0 (which it can't be). This can -lead to the following warning: - - lib/asn1_decoder.c:320 asn1_ber_decoder() - warn: unsigned 'len' is never less than zero. - -Instead, asn1_find_indefinite_length() update the caller's idea of the data -cursor and length separately from returning the error code. - -Reported-by: Dan Carpenter <dan.carpenter@oracle.com> -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - lib/asn1_decoder.c | 28 +++++++++++++++++++--------- - 1 file changed, 19 insertions(+), 9 deletions(-) - -diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c -index 2e4196d..de2c8b5 100644 ---- a/lib/asn1_decoder.c -+++ b/lib/asn1_decoder.c -@@ -46,12 +46,18 @@ static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { - - /* - * Find the length of an indefinite length object -+ * @data: The data buffer -+ * @datalen: The end of the innermost containing element in the buffer -+ * @_dp: The data parse cursor (updated before returning) -+ * @_len: Where to return the size of the element. -+ * @_errmsg: Where to return a pointer to an error message on error - */ - static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, -- const char **_errmsg, size_t *_err_dp) -+ size_t *_dp, size_t *_len, -+ const char **_errmsg) - { - unsigned char tag, tmp; -- size_t dp = 0, len, n; -+ size_t dp = *_dp, len, n; - int indef_level = 1; - - next_tag: -@@ -67,8 +73,11 @@ next_tag: - /* It appears to be an EOC. */ - if (data[dp++] != 0) - goto invalid_eoc; -- if (--indef_level <= 0) -- return dp; -+ if (--indef_level <= 0) { -+ *_len = dp - *_dp; -+ *_dp = dp; -+ return 0; -+ } - goto next_tag; - } - -@@ -122,7 +131,7 @@ data_overrun_error: - missing_eoc: - *_errmsg = "Missing EOC in indefinite len cons"; - error: -- *_err_dp = dp; -+ *_dp = dp; - return -1; - } - -@@ -315,13 +324,14 @@ next_op: - skip_data: - if (!(flags & FLAG_CONS)) { - if (flags & FLAG_INDEFINITE_LENGTH) { -- len = asn1_find_indefinite_length( -- data + dp, datalen - dp, &errmsg, &dp); -- if (len < 0) -+ ret = asn1_find_indefinite_length( -+ data, datalen, &dp, &len, &errmsg); -+ if (ret < 0) - goto error; -+ } else { -+ dp += len; - } - pr_debug("- LEAF: %zu\n", len); -- dp += len; - } - pc += asn1_op_lengths[op]; - goto next_op; --- -1.7.12.1 - - -From 4ae37452e7450971072481b98f6e1c29e5165c1e Mon Sep 17 00:00:00 2001 -From: Rusty Russell <rusty@rustcorp.com.au> -Date: Fri, 19 Oct 2012 11:53:15 +1030 -Subject: [PATCH 33/37] kbuild: sign the modules at install time - -Linus deleted the old code and put signing on the install command, -I fixed it to extract the keyid and signer-name within sign-file -and cleaned up that script now it always signs in-place. - -Some enthusiast should convert sign-key to perl and pull -x509keyid into it. - -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> -Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> ---- - Makefile | 11 +++++++ - scripts/Makefile.modinst | 2 +- - scripts/Makefile.modpost | 77 +----------------------------------------------- - scripts/sign-file | 44 +++++++++++---------------- - scripts/x509keyid | 16 +++++----- - 5 files changed, 39 insertions(+), 111 deletions(-) - -diff --git a/Makefile b/Makefile -index e4292ea..1cc5de4 100644 ---- a/Makefile -+++ b/Makefile -@@ -714,6 +714,17 @@ endif # INSTALL_MOD_STRIP - export mod_strip_cmd - - -+ifeq ($(CONFIG_MODULE_SIG),y) -+MODSECKEY = ./signing_key.priv -+MODPUBKEY = ./signing_key.x509 -+export MODPUBKEY -+mod_sign_cmd = sh $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) $(srctree)/scripts/x509keyid -+else -+mod_sign_cmd = true -+endif -+export mod_sign_cmd -+ -+ - ifeq ($(KBUILD_EXTMOD),) - core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ - -diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst -index efa5d94..38367bd 100644 ---- a/scripts/Makefile.modinst -+++ b/scripts/Makefile.modinst -@@ -17,7 +17,7 @@ __modinst: $(modules) - @: - - quiet_cmd_modules_install = INSTALL $@ -- cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) -+ cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) - - # Modules built outside the kernel source tree go into extra by default - INSTALL_MOD_DIR ?= extra -diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost -index 2a4d1a1..08dce14 100644 ---- a/scripts/Makefile.modpost -+++ b/scripts/Makefile.modpost -@@ -14,8 +14,7 @@ - # 3) create one <module>.mod.c file pr. module - # 4) create one Module.symvers file with CRC for all exported symbols - # 5) compile all <module>.mod.c files --# 6) final link of the module to a <module.ko> (or <module.unsigned>) file --# 7) signs the modules to a <module.ko> file -+# 6) final link of the module to a <module.ko> file - - # Step 3 is used to place certain information in the module's ELF - # section, including information such as: -@@ -33,8 +32,6 @@ - # Step 4 is solely used to allow module versioning in external modules, - # where the CRC of each module is retrieved from the Module.symvers file. - --# Step 7 is dependent on CONFIG_MODULE_SIG being enabled. -- - # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined - # symbols in the final module linking stage - # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. -@@ -119,7 +116,6 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE - targets += $(modules:.ko=.mod.o) - - # Step 6), final link of the modules --ifneq ($(CONFIG_MODULE_SIG),y) - quiet_cmd_ld_ko_o = LD [M] $@ - cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ - $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ -@@ -129,78 +125,7 @@ $(modules): %.ko :%.o %.mod.o FORCE - $(call if_changed,ld_ko_o) - - targets += $(modules) --else --quiet_cmd_ld_ko_unsigned_o = LD [M] $@ -- cmd_ld_ko_unsigned_o = \ -- $(LD) -r $(LDFLAGS) \ -- $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ -- -o $@ $(filter-out FORCE,$^) \ -- $(if $(AFTER_LINK),; $(AFTER_LINK)) -- --$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE -- $(call if_changed,ld_ko_unsigned_o) -- --targets += $(modules:.ko=.ko.unsigned) -- --# Step 7), sign the modules --MODSECKEY = ./signing_key.priv --MODPUBKEY = ./signing_key.x509 -- --ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY)) --ifeq ($(KBUILD_SRC),) -- # no O= is being used -- SCRIPTS_DIR := scripts --else -- SCRIPTS_DIR := $(KBUILD_SRC)/scripts --endif --SIGN_MODULES := 1 --else --SIGN_MODULES := 0 --endif -- --# only sign if it's an in-tree module --ifneq ($(KBUILD_EXTMOD),) --SIGN_MODULES := 0 --endif - --# We strip the module as best we can - note that using both strip and eu-strip --# results in a smaller module than using either alone. --EU_STRIP = $(shell which eu-strip || echo true) -- --quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@ -- cmd_sign_ko_stripped_ko_unsigned = \ -- cp $< $@ && \ -- strip -x -g $@ && \ -- $(EU_STRIP) $@ -- --ifeq ($(SIGN_MODULES),1) -- --quiet_cmd_genkeyid = GENKEYID $@ -- cmd_genkeyid = \ -- perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid -- --%.signer %.keyid: % -- $(call if_changed,genkeyid) -- --KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid --quiet_cmd_sign_ko_ko_stripped = SIGN [M] $@ -- cmd_sign_ko_ko_stripped = \ -- sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) $< $@ --else --KEYRING_DEP := --quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@ -- cmd_sign_ko_ko_unsigned = \ -- cp $< $@ --endif -- --$(modules): %.ko :%.ko.stripped $(KEYRING_DEP) FORCE -- $(call if_changed,sign_ko_ko_stripped) -- --$(patsubst %.ko,%.ko.stripped,$(modules)): %.ko.stripped :%.ko.unsigned FORCE -- $(call if_changed,sign_ko_stripped_ko_unsigned) -- --targets += $(modules) --endif - - # Add FORCE to the prequisites of a target to force it to be always rebuilt. - # --------------------------------------------------------------------------- -diff --git a/scripts/sign-file b/scripts/sign-file -index e58e34e..095a953 100644 ---- a/scripts/sign-file -+++ b/scripts/sign-file -@@ -1,8 +1,8 @@ --#!/bin/sh -+#!/bin/bash - # - # Sign a module file using the given key. - # --# Format: sign-file <key> <x509> <src-file> <dst-file> -+# Format: sign-file <key> <x509> <keyid-script> <module> - # - - scripts=`dirname $0` -@@ -15,8 +15,8 @@ fi - - key="$1" - x509="$2" --src="$3" --dst="$4" -+keyid_script="$3" -+mod="$4" - - if [ ! -r "$key" ] - then -@@ -29,16 +29,6 @@ then - echo "Can't read X.509 certificate" >&2 - exit 2 - fi --if [ ! -r "$x509.signer" ] --then -- echo "Can't read Signer name" >&2 -- exit 2; --fi --if [ ! -r "$x509.keyid" ] --then -- echo "Can't read Key identifier" >&2 -- exit 2; --fi - - # - # Signature parameters -@@ -83,33 +73,35 @@ fi - - ( - perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? --openssl dgst $dgst -binary $src || exit $? --) >$src.dig || exit $? -+openssl dgst $dgst -binary $mod || exit $? -+) >$mod.dig || exit $? - - # - # Generate the binary signature, which will be just the integer that comprises - # the signature with no metadata attached. - # --openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $? --signerlen=`stat -c %s $x509.signer` --keyidlen=`stat -c %s $x509.keyid` --siglen=`stat -c %s $src.sig` -+openssl rsautl -sign -inkey $key -keyform PEM -in $mod.dig -out $mod.sig || exit $? -+ -+SIGNER="`perl $keyid_script $x509 signer-name`" -+KEYID="`perl $keyid_script $x509 keyid`" -+keyidlen=${#KEYID} -+siglen=${#SIGNER} - - # - # Build the signed binary - # - ( -- cat $src || exit $? -+ cat $mod || exit $? - echo '~Module signature appended~' || exit $? -- cat $x509.signer $x509.keyid || exit $? -+ echo -n "$SIGNER" || exit $? -+ echo -n "$KEYID" || exit $? - - # Preface each signature integer with a 2-byte BE length - perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? -- cat $src.sig || exit $? -+ cat $mod.sig || exit $? - - # Generate the information block - perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? --) >$dst~ || exit $? -+) >$mod~ || exit $? - --# Permit in-place signing --mv $dst~ $dst || exit $? -+mv $mod~ $mod || exit $? -diff --git a/scripts/x509keyid b/scripts/x509keyid -index c8e91a4..4241ec6 100755 ---- a/scripts/x509keyid -+++ b/scripts/x509keyid -@@ -22,7 +22,7 @@ use strict; - - my $raw_data; - --die "Need three filenames\n" if ($#ARGV != 2); -+die "Need a filename [keyid|signer-name]\n" if ($#ARGV != 1); - - my $src = $ARGV[0]; - -@@ -259,10 +259,10 @@ die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" - - my $id_key_id = asn1_retrieve($subject_key_id->[1]); - --open(OUTFD, ">$ARGV[1]") || die $ARGV[1]; --print OUTFD $id_name; --close OUTFD || die $ARGV[1]; -- --open(OUTFD, ">$ARGV[2]") || die $ARGV[2]; --print OUTFD $id_key_id; --close OUTFD || die $ARGV[2]; -+if ($ARGV[1] eq "signer-name") { -+ print $id_name; -+} elsif ($ARGV[1] eq "keyid") { -+ print $id_key_id; -+} else { -+ die "Unknown arg"; -+} --- -1.7.12.1 - - -From 4aa23562520f07f4f27edb5c289bc289438005a0 Mon Sep 17 00:00:00 2001 -From: Linus Torvalds <torvalds@linux-foundation.org> -Date: Fri, 19 Oct 2012 12:43:19 -0700 -Subject: [PATCH 34/37] kbuild: Fix module signature generation - -Rusty had clearly not actually tested his module signing changes that I -(trustingly) applied as commit e2a666d52b48 ("kbuild: sign the modules -at install time"). That commit had multiple bugs: - - - using "${#VARIABLE}" to get the number of characters in a shell - variable may look clever, but it's locale-dependent: it returns the - number of *characters*, not bytes. And we do need bytes. - - So don't use "${#..}" expansion, do the stupid "wc -c" thing instead - (where "c" stands for "bytes", not "characters", despite the letter. - - - Rusty had confused "siglen" and "signerlen", and his conversion - didn't set "signerlen" at all, and incorrectly set "siglen" to the - size of the signer, not the size of the signature. - -End result: the modified sign-file script did create something that -superficially *looked* like a signature, but didn't actually work at -all, and would fail the signature check. Oops. - -Tssk, tssk, Rusty. - -But Rusty was definitely right that this whole thing should be rewritten -in perl by somebody who has the perl-fu to do so. That is not me, -though - I'm just doing an emergency fix for the shell script. - -Cc: Rusty Russell <rusty@rustcorp.com.au> -Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> ---- - scripts/sign-file | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/scripts/sign-file b/scripts/sign-file -index 095a953..d014abd 100644 ---- a/scripts/sign-file -+++ b/scripts/sign-file -@@ -81,11 +81,12 @@ openssl dgst $dgst -binary $mod || exit $? - # the signature with no metadata attached. - # - openssl rsautl -sign -inkey $key -keyform PEM -in $mod.dig -out $mod.sig || exit $? -+siglen=`stat -c %s $mod.sig` - - SIGNER="`perl $keyid_script $x509 signer-name`" - KEYID="`perl $keyid_script $x509 keyid`" --keyidlen=${#KEYID} --siglen=${#SIGNER} -+keyidlen=$(echo -n "$KEYID" | wc -c) -+signerlen=$(echo -n "$SIGNER" | wc -c) - - # - # Build the signed binary --- -1.7.12.1 - - -From f51b71db2cae9539acaa4d64a9e708d7aac1f879 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 19 Oct 2012 23:56:37 +0100 -Subject: [PATCH 35/37] MODSIGN: perlify sign-file and merge in x509keyid - -Turn sign-file into perl and merge in x509keyid. The latter doesn't -need to be a separate script as it doesn't actually need to work out the -SHA1 sum of the X.509 certificate itself, since it can get that from the -X.509 certificate. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> ---- - Makefile | 2 +- - scripts/sign-file | 477 +++++++++++++++++++++++++++++++++++++++++++++--------- - scripts/x509keyid | 268 ------------------------------ - 3 files changed, 400 insertions(+), 347 deletions(-) - mode change 100644 => 100755 scripts/sign-file - delete mode 100755 scripts/x509keyid - -diff --git a/Makefile b/Makefile -index 1cc5de4..f4f9cdb 100644 ---- a/Makefile -+++ b/Makefile -@@ -718,7 +718,7 @@ ifeq ($(CONFIG_MODULE_SIG),y) - MODSECKEY = ./signing_key.priv - MODPUBKEY = ./signing_key.x509 - export MODPUBKEY --mod_sign_cmd = sh $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) $(srctree)/scripts/x509keyid -+mod_sign_cmd = perl $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) - else - mod_sign_cmd = true - endif -diff --git a/scripts/sign-file b/scripts/sign-file -old mode 100644 -new mode 100755 -index d014abd..d37d130 ---- a/scripts/sign-file -+++ b/scripts/sign-file -@@ -1,108 +1,429 @@ --#!/bin/bash -+#!/usr/bin/perl -w - # - # Sign a module file using the given key. - # --# Format: sign-file <key> <x509> <keyid-script> <module> -+# Format: - # -+# ./scripts/sign-file [-v] <key> <x509> <module> [<dest>] -+# -+# -+use strict; -+use FileHandle; -+use IPC::Open2; -+ -+my $verbose = 0; -+if ($#ARGV >= 0 && $ARGV[0] eq "-v") { -+ $verbose = 1; -+ shift; -+} -+ -+die "Format: ./scripts/sign-file [-v] <key> <x509> <module> [<dest>]\n" -+ if ($#ARGV != 2 && $#ARGV != 3); -+ -+my $private_key = $ARGV[0]; -+my $x509 = $ARGV[1]; -+my $module = $ARGV[2]; -+my $dest = ($#ARGV == 3) ? $ARGV[3] : $ARGV[2] . "~"; -+ -+die "Can't read private key\n" unless (-r $private_key); -+die "Can't read X.509 certificate\n" unless (-r $x509); -+die "Can't read module\n" unless (-r $module); -+ -+# -+# Read the kernel configuration -+# -+my %config = ( -+ CONFIG_MODULE_SIG_SHA512 => 1 -+ ); -+ -+if (-r ".config") { -+ open(FD, "<.config") || die ".config"; -+ while (<FD>) { -+ if ($_ =~ /^(CONFIG_.*)=[ym]/) { -+ $config{$1} = 1; -+ } -+ } -+ close(FD); -+} - --scripts=`dirname $0` -+# -+# Function to read the contents of a file into a variable. -+# -+sub read_file($) -+{ -+ my ($file) = @_; -+ my $contents; -+ my $len; -+ -+ open(FD, "<$file") || die $file; -+ binmode FD; -+ my @st = stat(FD); -+ die $file if (!@st); -+ $len = read(FD, $contents, $st[7]) || die $file; -+ close(FD) || die $file; -+ die "$file: Wanted length ", $st[7], ", got ", $len, "\n" -+ if ($len != $st[7]); -+ return $contents; -+} -+ -+############################################################################### -+# -+# First of all, we have to parse the X.509 certificate to find certain details -+# about it. -+# -+# We read the DER-encoded X509 certificate and parse it to extract the Subject -+# name and Subject Key Identifier. Theis provides the data we need to build -+# the certificate identifier. -+# -+# The signer's name part of the identifier is fabricated from the commonName, -+# the organizationName or the emailAddress components of the X.509 subject -+# name. -+# -+# The subject key ID is used to select which of that signer's certificates -+# we're intending to use to sign the module. -+# -+############################################################################### -+my $x509_certificate = read_file($x509); - --CONFIG_MODULE_SIG_SHA512=y --if [ -r .config ] --then -- . ./.config --fi -+my $UNIV = 0 << 6; -+my $APPL = 1 << 6; -+my $CONT = 2 << 6; -+my $PRIV = 3 << 6; - --key="$1" --x509="$2" --keyid_script="$3" --mod="$4" -+my $CONS = 0x20; - --if [ ! -r "$key" ] --then -- echo "Can't read private key" >&2 -- exit 2 --fi -+my $BOOLEAN = 0x01; -+my $INTEGER = 0x02; -+my $BIT_STRING = 0x03; -+my $OCTET_STRING = 0x04; -+my $NULL = 0x05; -+my $OBJ_ID = 0x06; -+my $UTF8String = 0x0c; -+my $SEQUENCE = 0x10; -+my $SET = 0x11; -+my $UTCTime = 0x17; -+my $GeneralizedTime = 0x18; - --if [ ! -r "$x509" ] --then -- echo "Can't read X.509 certificate" >&2 -- exit 2 --fi -+my %OIDs = ( -+ pack("CCC", 85, 4, 3) => "commonName", -+ pack("CCC", 85, 4, 6) => "countryName", -+ pack("CCC", 85, 4, 10) => "organizationName", -+ pack("CCC", 85, 4, 11) => "organizationUnitName", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", -+ pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", -+ pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", -+ pack("CCC", 85, 29, 19) => "basicConstraints" -+); -+ -+############################################################################### -+# -+# Extract an ASN.1 element from a string and return information about it. -+# -+############################################################################### -+sub asn1_extract($$@) -+{ -+ my ($cursor, $expected_tag, $optional) = @_; -+ -+ return [ -1 ] -+ if ($cursor->[1] == 0 && $optional); -+ -+ die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" -+ if ($cursor->[1] < 2); -+ -+ my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); -+ -+ if ($expected_tag != -1 && $tag != $expected_tag) { -+ return [ -1 ] -+ if ($optional); -+ die $x509, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, -+ " not ", $expected_tag, ")\n"; -+ } -+ -+ $cursor->[0] += 2; -+ $cursor->[1] -= 2; -+ -+ die $x509, ": ", $cursor->[0], ": ASN.1 long tag\n" -+ if (($tag & 0x1f) == 0x1f); -+ die $x509, ": ", $cursor->[0], ": ASN.1 indefinite length\n" -+ if ($len == 0x80); -+ -+ if ($len > 0x80) { -+ my $l = $len - 0x80; -+ die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" -+ if ($cursor->[1] < $l); -+ -+ if ($l == 0x1) { -+ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); -+ } elsif ($l = 0x2) { -+ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); -+ } elsif ($l = 0x3) { -+ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; -+ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); -+ } elsif ($l = 0x4) { -+ $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); -+ } else { -+ die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; -+ } -+ -+ $cursor->[0] += $l; -+ $cursor->[1] -= $l; -+ } -+ -+ die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" -+ if ($cursor->[1] < $len); -+ -+ my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; -+ $cursor->[0] += $len; -+ $cursor->[1] -= $len; -+ -+ return $ret; -+} -+ -+############################################################################### -+# -+# Retrieve the data referred to by a cursor -+# -+############################################################################### -+sub asn1_retrieve($) -+{ -+ my ($cursor) = @_; -+ my ($offset, $len, $data) = @$cursor; -+ return substr($$data, $offset, $len); -+} -+ -+############################################################################### -+# -+# Roughly parse the X.509 certificate -+# -+############################################################################### -+my $cursor = [ 0, length($x509_certificate), \$x509_certificate ]; -+ -+my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); -+my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); -+my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); -+my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); -+my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); -+my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); -+my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); -+ -+my $subject_key_id = (); -+my $authority_key_id = (); -+ -+# -+# Parse the extension list -+# -+if ($extension_list->[0] != -1) { -+ my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); -+ -+ while ($extensions->[1]->[1] > 0) { -+ my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); -+ my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); -+ my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); -+ my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); -+ -+ my $raw_oid = asn1_retrieve($x_oid->[1]); -+ next if (!exists($OIDs{$raw_oid})); -+ my $x_type = $OIDs{$raw_oid}; -+ -+ my $raw_value = asn1_retrieve($x_val->[1]); -+ -+ if ($x_type eq "subjectKeyIdentifier") { -+ my $vcursor = [ 0, length($raw_value), \$raw_value ]; -+ -+ $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); -+ } -+ } -+} -+ -+############################################################################### -+# -+# Determine what we're going to use as the signer's name. In order of -+# preference, take one of: commonName, organizationName or emailAddress. -+# -+############################################################################### -+my $org = ""; -+my $cn = ""; -+my $email = ""; -+ -+while ($subject->[1]->[1] > 0) { -+ my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); -+ my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); -+ my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); -+ my $n_val = asn1_extract($attr->[1], -1); -+ -+ my $raw_oid = asn1_retrieve($n_oid->[1]); -+ next if (!exists($OIDs{$raw_oid})); -+ my $n_type = $OIDs{$raw_oid}; -+ -+ my $raw_value = asn1_retrieve($n_val->[1]); -+ -+ if ($n_type eq "organizationName") { -+ $org = $raw_value; -+ } elsif ($n_type eq "commonName") { -+ $cn = $raw_value; -+ } elsif ($n_type eq "emailAddress") { -+ $email = $raw_value; -+ } -+} -+ -+my $signers_name = $email; -+ -+if ($org && $cn) { -+ # Don't use the organizationName if the commonName repeats it -+ if (length($org) <= length($cn) && -+ substr($cn, 0, length($org)) eq $org) { -+ $signers_name = $cn; -+ goto got_id_name; -+ } -+ -+ # Or a signifcant chunk of it -+ if (length($org) >= 7 && -+ length($cn) >= 7 && -+ substr($cn, 0, 7) eq substr($org, 0, 7)) { -+ $signers_name = $cn; -+ goto got_id_name; -+ } -+ -+ $signers_name = $org . ": " . $cn; -+} elsif ($org) { -+ $signers_name = $org; -+} elsif ($cn) { -+ $signers_name = $cn; -+} -+ -+got_id_name: -+ -+die $x509, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" -+ if (!$subject_key_id); -+ -+my $key_identifier = asn1_retrieve($subject_key_id->[1]); -+ -+############################################################################### -+# -+# Create and attach the module signature -+# -+############################################################################### - - # - # Signature parameters - # --algo=1 # Public-key crypto algorithm: RSA --hash= # Digest algorithm --id_type=1 # Identifier type: X.509 -+my $algo = 1; # Public-key crypto algorithm: RSA -+my $hash = 0; # Digest algorithm -+my $id_type = 1; # Identifier type: X.509 - - # - # Digest the data - # --dgst= --if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ] --then -- prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14" -- dgst=-sha1 -- hash=2 --elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ] --then -- prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C" -- dgst=-sha224 -- hash=7 --elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ] --then -- prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20" -- dgst=-sha256 -- hash=4 --elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ] --then -- prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30" -- dgst=-sha384 -- hash=5 --elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ] --then -- prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40" -- dgst=-sha512 -- hash=6 --else -- echo "$0: Can't determine hash algorithm" >&2 -- exit 2 --fi -- --( --perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? --openssl dgst $dgst -binary $mod || exit $? --) >$mod.dig || exit $? -+my ($dgst, $prologue) = (); -+if (exists $config{"CONFIG_MODULE_SIG_SHA1"}) { -+ $prologue = pack("C*", -+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, -+ 0x2B, 0x0E, 0x03, 0x02, 0x1A, -+ 0x05, 0x00, 0x04, 0x14); -+ $dgst = "-sha1"; -+ $hash = 2; -+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA224"}) { -+ $prologue = pack("C*", -+ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, -+ 0x05, 0x00, 0x04, 0x1C); -+ $dgst = "-sha224"; -+ $hash = 7; -+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA256"}) { -+ $prologue = pack("C*", -+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, -+ 0x05, 0x00, 0x04, 0x20); -+ $dgst = "-sha256"; -+ $hash = 4; -+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA384"}) { -+ $prologue = pack("C*", -+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, -+ 0x05, 0x00, 0x04, 0x30); -+ $dgst = "-sha384"; -+ $hash = 5; -+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA512"}) { -+ $prologue = pack("C*", -+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, -+ 0x05, 0x00, 0x04, 0x40); -+ $dgst = "-sha512"; -+ $hash = 6; -+} else { -+ die "Can't determine hash algorithm"; -+} -+ -+# -+# Generate the digest and read from openssl's stdout -+# -+my $digest; -+$digest = readpipe("openssl dgst $dgst -binary $module") || die "openssl dgst"; - - # - # Generate the binary signature, which will be just the integer that comprises - # the signature with no metadata attached. - # --openssl rsautl -sign -inkey $key -keyform PEM -in $mod.dig -out $mod.sig || exit $? --siglen=`stat -c %s $mod.sig` -+my $pid; -+$pid = open2(*read_from, *write_to, -+ "openssl rsautl -sign -inkey $private_key -keyform PEM") || -+ die "openssl rsautl"; -+binmode write_to; -+print write_to $prologue . $digest || die "pipe to openssl rsautl"; -+close(write_to) || die "pipe to openssl rsautl"; -+ -+binmode read_from; -+my $signature; -+read(read_from, $signature, 4096) || die "pipe from openssl rsautl"; -+close(read_from) || die "pipe from openssl rsautl"; -+$signature = pack("n", length($signature)) . $signature, - --SIGNER="`perl $keyid_script $x509 signer-name`" --KEYID="`perl $keyid_script $x509 keyid`" --keyidlen=$(echo -n "$KEYID" | wc -c) --signerlen=$(echo -n "$SIGNER" | wc -c) -+waitpid($pid, 0) || die; -+die "openssl rsautl died: $?" if ($? >> 8); - - # - # Build the signed binary - # --( -- cat $mod || exit $? -- echo '~Module signature appended~' || exit $? -- echo -n "$SIGNER" || exit $? -- echo -n "$KEYID" || exit $? -+my $unsigned_module = read_file($module); -+ -+my $magic_number = "~Module signature appended~\n"; -+ -+my $info = pack("CCCCCxxxN", -+ $algo, $hash, $id_type, -+ length($signers_name), -+ length($key_identifier), -+ length($signature)); - -- # Preface each signature integer with a 2-byte BE length -- perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? -- cat $mod.sig || exit $? -+if ($verbose) { -+ print "Size of unsigned module: ", length($unsigned_module), "\n"; -+ print "Size of magic number : ", length($magic_number), "\n"; -+ print "Size of signer's name : ", length($signers_name), "\n"; -+ print "Size of key identifier : ", length($key_identifier), "\n"; -+ print "Size of signature : ", length($signature), "\n"; -+ print "Size of informaton : ", length($info), "\n"; -+ print "Signer's name : '", $signers_name, "'\n"; -+ print "Digest : $dgst\n"; -+} - -- # Generate the information block -- perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? --) >$mod~ || exit $? -+open(FD, ">$dest") || die $dest; -+binmode FD; -+print FD -+ $unsigned_module, -+ $magic_number, -+ $signers_name, -+ $key_identifier, -+ $signature, -+ $info -+ ; -+close FD || die $dest; - --mv $mod~ $mod || exit $? -+if ($#ARGV != 3) { -+ rename($dest, $module) || die $module; -+} -diff --git a/scripts/x509keyid b/scripts/x509keyid -deleted file mode 100755 -index 4241ec6..0000000 ---- a/scripts/x509keyid -+++ /dev/null -@@ -1,268 +0,0 @@ --#!/usr/bin/perl -w --# --# Generate an identifier from an X.509 certificate that can be placed in a --# module signature to indentify the key to use. --# --# Format: --# --# ./scripts/x509keyid <x509-cert> <signer's-name> <key-id> --# --# We read the DER-encoded X509 certificate and parse it to extract the Subject --# name and Subject Key Identifier. The provide the data we need to build the --# certificate identifier. --# --# The signer's name part of the identifier is fabricated from the commonName, --# the organizationName or the emailAddress components of the X.509 subject --# name and written to the second named file. --# --# The subject key ID to select which of that signer's certificates we're --# intending to use to sign the module is written to the third named file. --# --use strict; -- --my $raw_data; -- --die "Need a filename [keyid|signer-name]\n" if ($#ARGV != 1); -- --my $src = $ARGV[0]; -- --open(FD, "<$src") || die $src; --binmode FD; --my @st = stat(FD); --die $src if (!@st); --read(FD, $raw_data, $st[7]) || die $src; --close(FD); -- --my $UNIV = 0 << 6; --my $APPL = 1 << 6; --my $CONT = 2 << 6; --my $PRIV = 3 << 6; -- --my $CONS = 0x20; -- --my $BOOLEAN = 0x01; --my $INTEGER = 0x02; --my $BIT_STRING = 0x03; --my $OCTET_STRING = 0x04; --my $NULL = 0x05; --my $OBJ_ID = 0x06; --my $UTF8String = 0x0c; --my $SEQUENCE = 0x10; --my $SET = 0x11; --my $UTCTime = 0x17; --my $GeneralizedTime = 0x18; -- --my %OIDs = ( -- pack("CCC", 85, 4, 3) => "commonName", -- pack("CCC", 85, 4, 6) => "countryName", -- pack("CCC", 85, 4, 10) => "organizationName", -- pack("CCC", 85, 4, 11) => "organizationUnitName", -- pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", -- pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", -- pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", -- pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", -- pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", -- pack("CCC", 85, 29, 19) => "basicConstraints" --); -- --############################################################################### --# --# Extract an ASN.1 element from a string and return information about it. --# --############################################################################### --sub asn1_extract($$@) --{ -- my ($cursor, $expected_tag, $optional) = @_; -- -- return [ -1 ] -- if ($cursor->[1] == 0 && $optional); -- -- die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" -- if ($cursor->[1] < 2); -- -- my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); -- -- if ($expected_tag != -1 && $tag != $expected_tag) { -- return [ -1 ] -- if ($optional); -- die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, -- " not ", $expected_tag, ")\n"; -- } -- -- $cursor->[0] += 2; -- $cursor->[1] -= 2; -- -- die $src, ": ", $cursor->[0], ": ASN.1 long tag\n" -- if (($tag & 0x1f) == 0x1f); -- die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n" -- if ($len == 0x80); -- -- if ($len > 0x80) { -- my $l = $len - 0x80; -- die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" -- if ($cursor->[1] < $l); -- -- if ($l == 0x1) { -- $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); -- } elsif ($l = 0x2) { -- $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); -- } elsif ($l = 0x3) { -- $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; -- $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); -- } elsif ($l = 0x4) { -- $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); -- } else { -- die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; -- } -- -- $cursor->[0] += $l; -- $cursor->[1] -= $l; -- } -- -- die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" -- if ($cursor->[1] < $len); -- -- my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; -- $cursor->[0] += $len; -- $cursor->[1] -= $len; -- -- return $ret; --} -- --############################################################################### --# --# Retrieve the data referred to by a cursor --# --############################################################################### --sub asn1_retrieve($) --{ -- my ($cursor) = @_; -- my ($offset, $len, $data) = @$cursor; -- return substr($$data, $offset, $len); --} -- --############################################################################### --# --# Roughly parse the X.509 certificate --# --############################################################################### --my $cursor = [ 0, length($raw_data), \$raw_data ]; -- --my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); --my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); --my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); --my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); --my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); --my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); --my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); --my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); --my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); --my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); --my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); --my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); -- --my $subject_key_id = (); --my $authority_key_id = (); -- --# --# Parse the extension list --# --if ($extension_list->[0] != -1) { -- my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); -- -- while ($extensions->[1]->[1] > 0) { -- my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); -- my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); -- my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); -- my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); -- -- my $raw_oid = asn1_retrieve($x_oid->[1]); -- next if (!exists($OIDs{$raw_oid})); -- my $x_type = $OIDs{$raw_oid}; -- -- my $raw_value = asn1_retrieve($x_val->[1]); -- -- if ($x_type eq "subjectKeyIdentifier") { -- my $vcursor = [ 0, length($raw_value), \$raw_value ]; -- -- $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); -- } -- } --} -- --############################################################################### --# --# Determine what we're going to use as the signer's name. In order of --# preference, take one of: commonName, organizationName or emailAddress. --# --############################################################################### --my $org = ""; --my $cn = ""; --my $email = ""; -- --while ($subject->[1]->[1] > 0) { -- my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); -- my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); -- my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); -- my $n_val = asn1_extract($attr->[1], -1); -- -- my $raw_oid = asn1_retrieve($n_oid->[1]); -- next if (!exists($OIDs{$raw_oid})); -- my $n_type = $OIDs{$raw_oid}; -- -- my $raw_value = asn1_retrieve($n_val->[1]); -- -- if ($n_type eq "organizationName") { -- $org = $raw_value; -- } elsif ($n_type eq "commonName") { -- $cn = $raw_value; -- } elsif ($n_type eq "emailAddress") { -- $email = $raw_value; -- } --} -- --my $id_name = $email; -- --if ($org && $cn) { -- # Don't use the organizationName if the commonName repeats it -- if (length($org) <= length($cn) && -- substr($cn, 0, length($org)) eq $org) { -- $id_name = $cn; -- goto got_id_name; -- } -- -- # Or a signifcant chunk of it -- if (length($org) >= 7 && -- length($cn) >= 7 && -- substr($cn, 0, 7) eq substr($org, 0, 7)) { -- $id_name = $cn; -- goto got_id_name; -- } -- -- $id_name = $org . ": " . $cn; --} elsif ($org) { -- $id_name = $org; --} elsif ($cn) { -- $id_name = $cn; --} -- --got_id_name: -- --############################################################################### --# --# Output the signer's name and the key identifier that we're going to include --# in module signatures. --# --############################################################################### --die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" -- if (!$subject_key_id); -- --my $id_key_id = asn1_retrieve($subject_key_id->[1]); -- --if ($ARGV[1] eq "signer-name") { -- print $id_name; --} elsif ($ARGV[1] eq "keyid") { -- print $id_key_id; --} else { -- die "Unknown arg"; --} --- -1.7.12.1 - - -From 02c76d9df8ff5387b9131799750895475f87c351 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 19 Oct 2012 23:56:45 +0100 -Subject: [PATCH 36/37] MODSIGN: Cleanup .gitignore - -The module build process no longer creates intermediate files for module -signing, so remove them from .gitignore. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> ---- - .gitignore | 6 ------ - 1 file changed, 6 deletions(-) - -diff --git a/.gitignore b/.gitignore -index 0f2f40f..92bd0e4 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -14,10 +14,6 @@ - *.o.* - *.a - *.s --*.ko.unsigned --*.ko.stripped --*.ko.stripped.dig --*.ko.stripped.sig - *.ko - *.so - *.so.dbg -@@ -95,6 +91,4 @@ GTAGS - extra_certificates - signing_key.priv - signing_key.x509 --signing_key.x509.keyid --signing_key.x509.signer - x509.genkey --- -1.7.12.1 - - -From fd08dfdc1a0022b48b7a5d4599cb4d46bf099882 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Sat, 20 Oct 2012 01:19:29 +0100 -Subject: [PATCH 37/37] MODSIGN: Move the magic string to the end of a module - and eliminate the search - -Emit the magic string that indicates a module has a signature after the -signature data instead of before it. This allows module_sig_check() to -be made simpler and faster by the elimination of the search for the -magic string. Instead we just need to do a single memcmp(). - -This works because at the end of the signature data there is the -fixed-length signature information block. This block then falls -immediately prior to the magic number. - -From the contents of the information block, it is trivial to calculate -the size of the signature data and thus the size of the actual module -data. - -Signed-off-by: David Howells <dhowells@redhat.com> -Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> ---- - kernel/module-internal.h | 3 +-- - kernel/module.c | 26 +++++++++----------------- - kernel/module_signing.c | 24 +++++++++++++++--------- - scripts/sign-file | 6 +++--- - 4 files changed, 28 insertions(+), 31 deletions(-) - -diff --git a/kernel/module-internal.h b/kernel/module-internal.h -index 6114a13..24f9247 100644 ---- a/kernel/module-internal.h -+++ b/kernel/module-internal.h -@@ -11,5 +11,4 @@ - - extern struct key *modsign_keyring; - --extern int mod_verify_sig(const void *mod, unsigned long modlen, -- const void *sig, unsigned long siglen); -+extern int mod_verify_sig(const void *mod, unsigned long *_modlen); -diff --git a/kernel/module.c b/kernel/module.c -index 3e8b1a7..0cfcccc 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -2441,25 +2441,17 @@ static inline void kmemleak_load_module(const struct module *mod, - - #ifdef CONFIG_MODULE_SIG - static int module_sig_check(struct load_info *info, -- const void *mod, unsigned long *len) -+ const void *mod, unsigned long *_len) - { - int err = -ENOKEY; -- const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; -- const void *p = mod, *end = mod + *len; -- -- /* Poor man's memmem. */ -- while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { -- if (p + markerlen > end) -- break; -- -- if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { -- const void *sig = p + markerlen; -- /* Truncate module up to signature. */ -- *len = p - mod; -- err = mod_verify_sig(mod, *len, sig, end - sig); -- break; -- } -- p++; -+ unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; -+ unsigned long len = *_len; -+ -+ if (len > markerlen && -+ memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { -+ /* We truncate the module to discard the signature */ -+ *_len -= markerlen; -+ err = mod_verify_sig(mod, _len); - } - - if (!err) { -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index 6b09f69..d492a23 100644 ---- a/kernel/module_signing.c -+++ b/kernel/module_signing.c -@@ -183,27 +183,33 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, - /* - * Verify the signature on a module. - */ --int mod_verify_sig(const void *mod, unsigned long modlen, -- const void *sig, unsigned long siglen) -+int mod_verify_sig(const void *mod, unsigned long *_modlen) - { - struct public_key_signature *pks; - struct module_signature ms; - struct key *key; -- size_t sig_len; -+ const void *sig; -+ size_t modlen = *_modlen, sig_len; - int ret; - -- pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen); -+ pr_devel("==>%s(,%lu)\n", __func__, modlen); - -- if (siglen <= sizeof(ms)) -+ if (modlen <= sizeof(ms)) - return -EBADMSG; - -- memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms)); -- siglen -= sizeof(ms); -+ memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); -+ modlen -= sizeof(ms); - - sig_len = be32_to_cpu(ms.sig_len); -- if (sig_len >= siglen || -- siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len) -+ if (sig_len >= modlen) - return -EBADMSG; -+ modlen -= sig_len; -+ if ((size_t)ms.signer_len + ms.key_id_len >= modlen) -+ return -EBADMSG; -+ modlen -= (size_t)ms.signer_len + ms.key_id_len; -+ -+ *_modlen = modlen; -+ sig = mod + modlen; - - /* For the moment, only support RSA and X.509 identifiers */ - if (ms.algo != PKEY_ALGO_RSA || -diff --git a/scripts/sign-file b/scripts/sign-file -index d37d130..87ca59d 100755 ---- a/scripts/sign-file -+++ b/scripts/sign-file -@@ -403,11 +403,11 @@ my $info = pack("CCCCCxxxN", - - if ($verbose) { - print "Size of unsigned module: ", length($unsigned_module), "\n"; -- print "Size of magic number : ", length($magic_number), "\n"; - print "Size of signer's name : ", length($signers_name), "\n"; - print "Size of key identifier : ", length($key_identifier), "\n"; - print "Size of signature : ", length($signature), "\n"; - print "Size of informaton : ", length($info), "\n"; -+ print "Size of magic number : ", length($magic_number), "\n"; - print "Signer's name : '", $signers_name, "'\n"; - print "Digest : $dgst\n"; - } -@@ -416,11 +416,11 @@ open(FD, ">$dest") || die $dest; - binmode FD; - print FD - $unsigned_module, -- $magic_number, - $signers_name, - $key_identifier, - $signature, -- $info -+ $info, -+ $magic_number - ; - close FD || die $dest; - --- -1.7.12.1 - -From f6a79af8f3701b5a0df431a76adee212616154dc Mon Sep 17 00:00:00 2001 -From: Rusty Russell <rusty@rustcorp.com.au> -Date: Tue, 6 Nov 2012 11:46:59 +1030 -Subject: [PATCH] modules: don't break modules_install on external modules - with no key. - -The script still spits out an error ("Can't read private key") but we -don't break modules_install. - -Reported-by: Bruno Wolff III <bruno@wolff.to> -Original-patch-by: Josh Boyer <jwboyer@redhat.com> -Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> ---- - scripts/Makefile.modinst | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst -index dda4b2b..ecbb447 100644 ---- a/scripts/Makefile.modinst -+++ b/scripts/Makefile.modinst -@@ -16,8 +16,9 @@ PHONY += $(modules) - __modinst: $(modules) - @: - -+# Don't stop modules_install if we can't sign external modules. - quiet_cmd_modules_install = INSTALL $@ -- cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) -+ cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) - - # Modules built outside the kernel source tree go into extra by default - INSTALL_MOD_DIR ?= extra --- -1.7.6.5 - diff --git a/freed-ora/current/f18/patch-3.6-gnu-3.6.11-gnu.xz.sign b/freed-ora/current/f18/patch-3.6-gnu-3.6.11-gnu.xz.sign deleted file mode 100644 index b6f9b307c..000000000 --- a/freed-ora/current/f18/patch-3.6-gnu-3.6.11-gnu.xz.sign +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2.0.18 (GNU/Linux) - -iEYEABECAAYFAlDPnLwACgkQvLfPh359R6cYogCfXcKutcYI0E1kffdoSPnlCJU3 -3ZQAnRuh1P/7RkYtUpaplVdCUETQ0u7g -=cIkL ------END PGP SIGNATURE----- diff --git a/freed-ora/current/f18/secure-boot-20121212.patch b/freed-ora/current/f18/secure-boot-20121212.patch index d435eb217..387302b90 100644 --- a/freed-ora/current/f18/secure-boot-20121212.patch +++ b/freed-ora/current/f18/secure-boot-20121212.patch @@ -1,4 +1,4 @@ -From 925befaba2477067aa12fa1fdc9fcc135c80b4fd Mon Sep 17 00:00:00 2001 +From d510ea864f470d96aafb75d0de7f09450407095e Mon Sep 17 00:00:00 2001 From: Matthew Garrett <mjg@redhat.com> Date: Thu, 20 Sep 2012 10:40:56 -0400 Subject: [PATCH 01/20] Secure boot: Add new capability @@ -11,14 +11,14 @@ capability set if required. Signed-off-by: Matthew Garrett <mjg@redhat.com> --- - include/linux/capability.h | 6 +++++- + include/uapi/linux/capability.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) -diff --git a/include/linux/capability.h b/include/linux/capability.h -index d10b7ed..4345bc8 100644 ---- a/include/linux/capability.h -+++ b/include/linux/capability.h -@@ -364,7 +364,11 @@ struct cpu_vfs_cap_data { +diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h +index ba478fa..7109e65 100644 +--- a/include/uapi/linux/capability.h ++++ b/include/uapi/linux/capability.h +@@ -343,7 +343,11 @@ struct vfs_cap_data { #define CAP_BLOCK_SUSPEND 36 @@ -35,7 +35,7 @@ index d10b7ed..4345bc8 100644 1.8.0.1 -From 1c5873679d750bda038d22210d9fd40c8673211f Mon Sep 17 00:00:00 2001 +From a07ae01ac4b304ac7f0e2b5d4193519f1a9eee8d Mon Sep 17 00:00:00 2001 From: Matthew Garrett <mjg@redhat.com> Date: Thu, 20 Sep 2012 10:40:57 -0400 Subject: [PATCH 02/20] PCI: Lock down BAR access in secure boot environments @@ -87,7 +87,7 @@ index f39378d..1db1e74 100644 } diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c -index af028c7..53372eb 100644 +index 9b8505c..35580bc 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -139,6 +139,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof @@ -136,7 +136,7 @@ index e1c1ec5..97e785f 100644 1.8.0.1 -From f067c7702f46b85d06da6c34dd907b44e594c2cf Mon Sep 17 00:00:00 2001 +From 1b5a1b53577992b32a3f51b18aa07cb9b300a3b1 Mon Sep 17 00:00:00 2001 From: Matthew Garrett <mjg@redhat.com> Date: Thu, 20 Sep 2012 10:40:58 -0400 Subject: [PATCH 03/20] x86: Lock down IO port access in secure boot @@ -176,7 +176,7 @@ index 8c96897..a2578c4 100644 } regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index e5eedfa..1e0a660 100644 +index 0537903..47501fc 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -597,6 +597,9 @@ static ssize_t write_port(struct file *file, const char __user *buf, @@ -193,7 +193,7 @@ index e5eedfa..1e0a660 100644 1.8.0.1 -From 95b440833e9002bc7e1950f403f2fb2953b69317 Mon Sep 17 00:00:00 2001 +From 09c266136915eb1f4a9b36423b7ba65e3d024de4 Mon Sep 17 00:00:00 2001 From: Matthew Garrett <mjg@redhat.com> Date: Thu, 20 Sep 2012 10:40:59 -0400 Subject: [PATCH 04/20] ACPI: Limit access to custom_method @@ -225,7 +225,7 @@ index 5d42c24..247d58b 100644 1.8.0.1 -From fd40b868d55992f71acffa74b559923ffde81638 Mon Sep 17 00:00:00 2001 +From f3e9cb16e5ab3e680ec3ef464682c52371bbbbe3 Mon Sep 17 00:00:00 2001 From: Matthew Garrett <mjg@redhat.com> Date: Thu, 20 Sep 2012 10:41:00 -0400 Subject: [PATCH 05/20] asus-wmi: Restrict debugfs interface @@ -278,7 +278,7 @@ index c0e9ff4..3c10167 100644 1.8.0.1 -From 470e4dbf6215d40a340b3ad7fd6d4533ffbf6a6d Mon Sep 17 00:00:00 2001 +From 23372d2a40135aca7a6d73511bd88790b598b489 Mon Sep 17 00:00:00 2001 From: Matthew Garrett <mjg@redhat.com> Date: Thu, 20 Sep 2012 10:41:01 -0400 Subject: [PATCH 06/20] Restrict /dev/mem and /dev/kmem in secure boot setups @@ -292,7 +292,7 @@ Signed-off-by: Matthew Garrett <mjg@redhat.com> 1 file changed, 6 insertions(+) diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index 1e0a660..33eb947 100644 +index 47501fc..8817cdc 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -158,6 +158,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf, @@ -319,7 +319,7 @@ index 1e0a660..33eb947 100644 1.8.0.1 -From fdb24af2d20faea8bae60058f0cda8db8be9394d Mon Sep 17 00:00:00 2001 +From a0c80b01e80a1f6484a2a2811b4a212322494614 Mon Sep 17 00:00:00 2001 From: Josh Boyer <jwboyer@redhat.com> Date: Thu, 20 Sep 2012 10:41:02 -0400 Subject: [PATCH 07/20] Secure boot: Add a dummy kernel parameter that will @@ -336,10 +336,10 @@ Signed-off-by: Josh Boyer <jwboyer@redhat.com> 2 files changed, 24 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 9b2b8d3..93978d5 100644 +index 9776f06..0d6c28d 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt -@@ -2562,6 +2562,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. +@@ -2599,6 +2599,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Note: increases power consumption, thus should only be enabled if running jitter sensitive (HPC/RT) workloads. @@ -354,7 +354,7 @@ index 9b2b8d3..93978d5 100644 If this boot parameter is not specified, only the first security module asking for security registration will be diff --git a/kernel/cred.c b/kernel/cred.c -index de728ac..7e6e83f 100644 +index 48cea3d..3f5be65 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -623,6 +623,23 @@ void __init cred_init(void) @@ -385,7 +385,7 @@ index de728ac..7e6e83f 100644 1.8.0.1 -From 033a0db83fe140b040a5f5a5754ba326b0d4f587 Mon Sep 17 00:00:00 2001 +From 640f088c49da87a344417f58d3faa72d63a4f6ed Mon Sep 17 00:00:00 2001 From: Matthew Garrett <mjg@redhat.com> Date: Thu, 20 Sep 2012 10:41:03 -0400 Subject: [PATCH 08/20] efi: Enable secure boot lockdown automatically when @@ -418,10 +418,10 @@ index cf5437d..7f9ed48 100644 2D0/A00 ALL e820_map E820 memory map table (array of struct e820entry) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index 90201aa..bdf0eb7 100644 +index e87b0ca..260cace 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c -@@ -726,6 +726,36 @@ fail: +@@ -732,6 +732,36 @@ fail: return status; } @@ -458,7 +458,7 @@ index 90201aa..bdf0eb7 100644 /* * Because the x86 boot code expects to be passed a boot_params we * need to create one ourselves (usually the bootloader would create -@@ -1020,6 +1050,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, +@@ -1026,6 +1056,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) goto fail; @@ -482,10 +482,10 @@ index 2ad874c..c7338e0 100644 __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index 5cee802..b4f4666 100644 +index ca45696..800673d 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c -@@ -961,6 +961,9 @@ void __init setup_arch(char **cmdline_p) +@@ -962,6 +962,9 @@ void __init setup_arch(char **cmdline_p) io_delay_init(); @@ -512,7 +512,7 @@ index ebbed2c..a24faf1 100644 1.8.0.1 -From 7a24fb283b72797e219a3283c5cf880ebb80443f Mon Sep 17 00:00:00 2001 +From 994d895b5b684fc53c3b43dda9aee460c1f526f2 Mon Sep 17 00:00:00 2001 From: Josh Boyer <jwboyer@redhat.com> Date: Thu, 20 Sep 2012 10:41:04 -0400 Subject: [PATCH 09/20] acpi: Ignore acpi_rsdp kernel parameter in a secure @@ -544,7 +544,7 @@ index 9eaf708..f94341b 100644 1.8.0.1 -From a21ccbd8461fd9780c348faa78bbd3d13db04e3d Mon Sep 17 00:00:00 2001 +From c80aaf3eee3cb6b0d1a051e418ee99cd238c868c Mon Sep 17 00:00:00 2001 From: Josh Boyer <jwboyer@redhat.com> Date: Thu, 20 Sep 2012 10:41:05 -0400 Subject: [PATCH 10/20] SELinux: define mapping for new Secure Boot capability @@ -577,7 +577,7 @@ index df2de54..70e2834 100644 1.8.0.1 -From 01af02988477c4bde39436adec1edfd1499709d9 Mon Sep 17 00:00:00 2001 +From 26352bcb92468233dd960b5d02ba1db344df72b9 Mon Sep 17 00:00:00 2001 From: Matthew Garrett <mjg@redhat.com> Date: Tue, 4 Sep 2012 11:55:13 -0400 Subject: [PATCH 11/20] kexec: Disable in a secure boot environment @@ -593,10 +593,10 @@ Signed-off-by: Matthew Garrett <mjg@redhat.com> 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/kexec.c b/kernel/kexec.c -index 0668d58..8b976a5 100644 +index 5e4bd78..dd464e0 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c -@@ -944,7 +944,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, +@@ -943,7 +943,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, int result; /* We only trust the superuser with rebooting the system. */ @@ -609,7 +609,7 @@ index 0668d58..8b976a5 100644 1.8.0.1 -From 883409d0fadeefe2c44d7034d2acc0e366c339f3 Mon Sep 17 00:00:00 2001 +From c03c68adceaec9656c55c47190fb4243bf903b40 Mon Sep 17 00:00:00 2001 From: Josh Boyer <jwboyer@redhat.com> Date: Mon, 25 Jun 2012 21:29:46 -0400 Subject: [PATCH 12/20] Documentation: kernel-parameters.txt remove @@ -630,7 +630,7 @@ Signed-off-by: Josh Boyer <jwboyer@redhat.com> 1 file changed, 6 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 93978d5..e3e5f8c 100644 +index 0d6c28d..d9af501 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -446,12 +446,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. @@ -650,7 +650,7 @@ index 93978d5..e3e5f8c 100644 1.8.0.1 -From b2ee7008ee39d04b3439f81e42586ee8e16af2e9 Mon Sep 17 00:00:00 2001 +From 3f1bda64d2c7b369e2833bd32cd1f3ba6c90348f Mon Sep 17 00:00:00 2001 From: Josh Boyer <jwboyer@redhat.com> Date: Fri, 5 Oct 2012 10:12:48 -0400 Subject: [PATCH 13/20] modsign: Always enforce module signing in a Secure Boot @@ -669,7 +669,7 @@ Signed-off-by: Josh Boyer <jwboyer@redhat.com> 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/kernel/cred.c b/kernel/cred.c -index 7e6e83f..6e828e2 100644 +index 3f5be65..a381e27 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -623,11 +623,19 @@ void __init cred_init(void) @@ -693,7 +693,7 @@ index 7e6e83f..6e828e2 100644 /* Dummy Secure Boot enable option to fake out UEFI SB=1 */ diff --git a/kernel/module.c b/kernel/module.c -index e0785b3..b964a03 100644 +index 6e48c3a..6d5d2aa 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -106,9 +106,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ @@ -712,7 +712,7 @@ index e0785b3..b964a03 100644 1.8.0.1 -From 4fe6ecce3e9168f538fc8970fe8a964438beabbb Mon Sep 17 00:00:00 2001 +From e6e3ec77b2fa037b32829e7f5ee468ad8a62dd05 Mon Sep 17 00:00:00 2001 From: Dave Howells <dhowells@redhat.com> Date: Tue, 23 Oct 2012 09:30:54 -0400 Subject: [PATCH 14/20] Add EFI signature data types, such as are used for @@ -724,7 +724,7 @@ Signed-off-by: David Howells <dhowells@redhat.com> 1 file changed, 20 insertions(+) diff --git a/include/linux/efi.h b/include/linux/efi.h -index bff4b5e..52ce2c4 100644 +index 337aefb..a01f8a7 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -317,6 +317,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, @@ -765,7 +765,7 @@ index bff4b5e..52ce2c4 100644 1.8.0.1 -From 768ab9ef88b2caa9588e577fe547792dfe513fca Mon Sep 17 00:00:00 2001 +From c2542256f632a22232cf02d5fd64568a5afa4516 Mon Sep 17 00:00:00 2001 From: Dave Howells <dhowells@redhat.com> Date: Tue, 23 Oct 2012 09:36:28 -0400 Subject: [PATCH 15/20] Add an EFI signature blob parser and key loader. X.509 @@ -922,10 +922,10 @@ index 0000000..59b859a + return 0; +} diff --git a/include/linux/efi.h b/include/linux/efi.h -index 52ce2c4..54b5936 100644 +index a01f8a7..44a7faa 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -538,6 +538,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); +@@ -541,6 +541,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); extern void efi_reserve_boot_services(void); extern struct efi_memory_map memmap; @@ -940,7 +940,7 @@ index 52ce2c4..54b5936 100644 1.8.0.1 -From 967a1b02af199f07fd7603bda2f0aeec50b412b9 Mon Sep 17 00:00:00 2001 +From a418e6fdd2aa946a30cf1bee5c9540d03d626981 Mon Sep 17 00:00:00 2001 From: Josh Boyer <jwboyer@redhat.com> Date: Fri, 26 Oct 2012 12:29:49 -0400 Subject: [PATCH 16/20] EFI: Add in-kernel variable to determine if Secure Boot @@ -959,10 +959,10 @@ Signed-off-by: Josh Boyer <jwboyer@redhat.com> 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index b4f4666..db74940 100644 +index 800673d..cf8823b 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c -@@ -961,8 +961,12 @@ void __init setup_arch(char **cmdline_p) +@@ -962,8 +962,12 @@ void __init setup_arch(char **cmdline_p) io_delay_init(); @@ -977,10 +977,10 @@ index b4f4666..db74940 100644 /* * Parse the ACPI tables for possible boot-time SMP configuration. diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index 72d8899..882d794 100644 +index ad44391..d22bfeb 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c -@@ -53,6 +53,8 @@ +@@ -54,6 +54,8 @@ int efi_enabled; EXPORT_SYMBOL(efi_enabled); @@ -990,10 +990,10 @@ index 72d8899..882d794 100644 .mps = EFI_INVALID_TABLE_ADDR, .acpi = EFI_INVALID_TABLE_ADDR, diff --git a/include/linux/efi.h b/include/linux/efi.h -index 54b5936..411997f 100644 +index 44a7faa..b5403ae 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -575,11 +575,14 @@ extern int __init efi_setup_pcdp_console(char *); +@@ -578,11 +578,14 @@ extern int __init efi_setup_pcdp_console(char *); # ifdef CONFIG_X86 extern int efi_enabled; extern bool efi_64bit; @@ -1012,7 +1012,7 @@ index 54b5936..411997f 100644 1.8.0.1 -From 6e946d64dc843d9caa587780801de035b38fd4b3 Mon Sep 17 00:00:00 2001 +From f6d05f0974f6a7667ebbbf91624678bcf32169ae Mon Sep 17 00:00:00 2001 From: Josh Boyer <jwboyer@redhat.com> Date: Fri, 26 Oct 2012 12:36:24 -0400 Subject: [PATCH 17/20] MODSIGN: Add module certificate blacklist keyring @@ -1031,10 +1031,10 @@ Signed-off-by: Josh Boyer <jwboyer@redhat.com> 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/init/Kconfig b/init/Kconfig -index abc6e63..78f3e280 100644 +index 6fdd6e3..7a9bf00 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -1613,6 +1613,14 @@ config MODULE_SIG_FORCE +@@ -1602,6 +1602,14 @@ config MODULE_SIG_FORCE Reject unsigned modules or signed modules for which we don't have a key. Without this, such modules will simply taint the kernel. @@ -1050,7 +1050,7 @@ index abc6e63..78f3e280 100644 prompt "Which hash algorithm should modules be signed with?" depends on MODULE_SIG diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c -index 4646eb2..6d70783 100644 +index 767e559..3bfb7ed 100644 --- a/kernel/modsign_pubkey.c +++ b/kernel/modsign_pubkey.c @@ -17,6 +17,9 @@ @@ -1098,7 +1098,7 @@ index 24f9247..51a8380 100644 extern int mod_verify_sig(const void *mod, unsigned long *_modlen); diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index d492a23..39131d3 100644 +index f2970bd..8ab83a6 100644 --- a/kernel/module_signing.c +++ b/kernel/module_signing.c @@ -132,7 +132,7 @@ static int mod_extract_mpi_array(struct public_key_signature *pks, @@ -1133,7 +1133,7 @@ index d492a23..39131d3 100644 1.8.0.1 -From 02905ddf41b18af3c3dd5d99771eba4e453d24ca Mon Sep 17 00:00:00 2001 +From ff0ed221fe8d5a46a9bc36323ca8fb6f75c22a83 Mon Sep 17 00:00:00 2001 From: Josh Boyer <jwboyer@redhat.com> Date: Fri, 26 Oct 2012 12:42:16 -0400 Subject: [PATCH 18/20] MODSIGN: Import certificates from UEFI Secure Boot @@ -1161,7 +1161,7 @@ Signed-off-by: Josh Boyer <jwboyer@redhat.com> create mode 100644 kernel/modsign_uefi.c diff --git a/include/linux/efi.h b/include/linux/efi.h -index 411997f..31f84ff 100644 +index b5403ae..bba53e3 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -323,6 +323,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, @@ -1178,10 +1178,10 @@ index 411997f..31f84ff 100644 efi_guid_t guid; u64 table; diff --git a/init/Kconfig b/init/Kconfig -index 78f3e280..754ee66 100644 +index 7a9bf00..51aa170 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -1621,6 +1621,15 @@ config MODULE_SIG_BLACKLIST +@@ -1610,6 +1610,15 @@ config MODULE_SIG_BLACKLIST should not pass module signature verification. If a module is signed with something in this keyring, the load will be rejected. @@ -1198,10 +1198,10 @@ index 78f3e280..754ee66 100644 prompt "Which hash algorithm should modules be signed with?" depends on MODULE_SIG diff --git a/kernel/Makefile b/kernel/Makefile -index d3611c8..927a264 100644 +index 86e3285..12e17ab 100644 --- a/kernel/Makefile +++ b/kernel/Makefile -@@ -56,6 +56,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o +@@ -55,6 +55,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o @@ -1209,7 +1209,7 @@ index d3611c8..927a264 100644 obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_KEXEC) += kexec.o -@@ -114,6 +115,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o +@@ -113,6 +114,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o $(obj)/configs.o: $(obj)/config_data.h @@ -1318,7 +1318,7 @@ index 0000000..76a5a34 1.8.0.1 -From b1bc4417dcec5c603baae2de2523bdf3a0c96b11 Mon Sep 17 00:00:00 2001 +From 7d5629a2000d9dc92da91d2f1258af748e89cfd7 Mon Sep 17 00:00:00 2001 From: Josh Boyer <jwboyer@redhat.com> Date: Fri, 26 Oct 2012 14:02:09 -0400 Subject: [PATCH 19/20] hibernate: Disable in a Secure Boot environment @@ -1414,7 +1414,7 @@ index 4ed81e7..b11a0f4 100644 1.8.0.1 -From 96c9c61996828908833b680149525b4b7acff664 Mon Sep 17 00:00:00 2001 +From 81adc779dba0f45f10b5ff307bd55832305f1112 Mon Sep 17 00:00:00 2001 From: Josh Boyer <jwboyer@redhat.com> Date: Wed, 12 Dec 2012 11:48:49 -0500 Subject: [PATCH 20/20] Don't soft lockup on bad EFI signature lists diff --git a/freed-ora/current/f18/smp_irq_move_cleanup_interrupt.patch b/freed-ora/current/f18/smp_irq_move_cleanup_interrupt.patch deleted file mode 100644 index c9b385a94..000000000 --- a/freed-ora/current/f18/smp_irq_move_cleanup_interrupt.patch +++ /dev/null @@ -1,50 +0,0 @@ -commit 94777fc51b3ad85ff9f705ddf7cdd0eb3bbad5a6 -Author: Dimitri Sivanich <sivanich@sgi.com> -Date: Tue Oct 16 07:50:21 2012 -0500 - - x86/irq/ioapic: Check for valid irq_cfg pointer in smp_irq_move_cleanup_interrupt - - Posting this patch to fix an issue concerning sparse irq's that - I raised a while back. There was discussion about adding - refcounting to sparse irqs (to fix other potential race - conditions), but that does not appear to have been addressed - yet. This covers the only issue of this type that I've - encountered in this area. - - A NULL pointer dereference can occur in - smp_irq_move_cleanup_interrupt() if we haven't yet setup the - irq_cfg pointer in the irq_desc.irq_data.chip_data. - - In create_irq_nr() there is a window where we have set - vector_irq in __assign_irq_vector(), but not yet called - irq_set_chip_data() to set the irq_cfg pointer. - - Should an IRQ_MOVE_CLEANUP_VECTOR hit the cpu in question during - this time, smp_irq_move_cleanup_interrupt() will attempt to - process the aforementioned irq, but panic when accessing - irq_cfg. - - Only continue processing the irq if irq_cfg is non-NULL. - - Signed-off-by: Dimitri Sivanich <sivanich@sgi.com> - Cc: Suresh Siddha <suresh.b.siddha@intel.com> - Cc: Joerg Roedel <joerg.roedel@amd.com> - Cc: Yinghai Lu <yinghai@kernel.org> - Cc: Alexander Gordeev <agordeev@redhat.com> - Link: http://lkml.kernel.org/r/20121016125021.GA22935@sgi.com - Signed-off-by: Ingo Molnar <mingo@kernel.org> - -diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c -index c265593..1817fa9 100644 ---- a/arch/x86/kernel/apic/io_apic.c -+++ b/arch/x86/kernel/apic/io_apic.c -@@ -2257,6 +2257,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void) - continue; - - cfg = irq_cfg(irq); -+ if (!cfg) -+ continue; -+ - raw_spin_lock(&desc->lock); - - /* diff --git a/freed-ora/current/f18/sources b/freed-ora/current/f18/sources index 4362eb911..e54b5c017 100644 --- a/freed-ora/current/f18/sources +++ b/freed-ora/current/f18/sources @@ -1,2 +1,2 @@ -a2312edd0265b5b07bd4b50afae2b380 linux-libre-3.6-gnu.tar.xz -ced16b674906cf8c3733c012f804f5c7 patch-3.6-gnu-3.6.11-gnu.xz +06bf9601d859531e7378eb43d4ca7dd3 linux-libre-3.7-gnu.tar.xz +48f5f530b048e387e978e3e49de7742a patch-3.7.1.xz diff --git a/freed-ora/current/f18/team-net-next-20120808.patch b/freed-ora/current/f18/team-net-next-20120808.patch deleted file mode 100644 index c738a4724..000000000 --- a/freed-ora/current/f18/team-net-next-20120808.patch +++ /dev/null @@ -1,499 +0,0 @@ -Update team driver to latest net-next. - -Split patches available here: -http://people.redhat.com/jpirko/f18_team_update_2/ - -Jiri Pirko (4): - netlink: add signed types - team: add signed 32-bit team option type - team: add per port priority option - team: add support for queue override by setting queue_id for port - - drivers/net/team/team.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++- - include/linux/if_team.h | 7 ++ - include/net/netlink.h | 98 +++++++++++++++++++++++ - 3 files changed, 303 insertions(+), 2 deletions(-) - -Signed-off-by: Jiri Pirko <jpirko@redhat.com> - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 87707ab..ba10c46 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -658,6 +658,122 @@ static rx_handler_result_t team_handle_frame(struct sk_buff **pskb) - } - - -+/************************************* -+ * Multiqueue Tx port select override -+ *************************************/ -+ -+static int team_queue_override_init(struct team *team) -+{ -+ struct list_head *listarr; -+ unsigned int queue_cnt = team->dev->num_tx_queues - 1; -+ unsigned int i; -+ -+ if (!queue_cnt) -+ return 0; -+ listarr = kmalloc(sizeof(struct list_head) * queue_cnt, GFP_KERNEL); -+ if (!listarr) -+ return -ENOMEM; -+ team->qom_lists = listarr; -+ for (i = 0; i < queue_cnt; i++) -+ INIT_LIST_HEAD(listarr++); -+ return 0; -+} -+ -+static void team_queue_override_fini(struct team *team) -+{ -+ kfree(team->qom_lists); -+} -+ -+static struct list_head *__team_get_qom_list(struct team *team, u16 queue_id) -+{ -+ return &team->qom_lists[queue_id - 1]; -+} -+ -+/* -+ * note: already called with rcu_read_lock -+ */ -+static bool team_queue_override_transmit(struct team *team, struct sk_buff *skb) -+{ -+ struct list_head *qom_list; -+ struct team_port *port; -+ -+ if (!team->queue_override_enabled || !skb->queue_mapping) -+ return false; -+ qom_list = __team_get_qom_list(team, skb->queue_mapping); -+ list_for_each_entry_rcu(port, qom_list, qom_list) { -+ if (!team_dev_queue_xmit(team, port, skb)) -+ return true; -+ } -+ return false; -+} -+ -+static void __team_queue_override_port_del(struct team *team, -+ struct team_port *port) -+{ -+ list_del_rcu(&port->qom_list); -+ synchronize_rcu(); -+ INIT_LIST_HEAD(&port->qom_list); -+} -+ -+static bool team_queue_override_port_has_gt_prio_than(struct team_port *port, -+ struct team_port *cur) -+{ -+ if (port->priority < cur->priority) -+ return true; -+ if (port->priority > cur->priority) -+ return false; -+ if (port->index < cur->index) -+ return true; -+ return false; -+} -+ -+static void __team_queue_override_port_add(struct team *team, -+ struct team_port *port) -+{ -+ struct team_port *cur; -+ struct list_head *qom_list; -+ struct list_head *node; -+ -+ if (!port->queue_id || !team_port_enabled(port)) -+ return; -+ -+ qom_list = __team_get_qom_list(team, port->queue_id); -+ node = qom_list; -+ list_for_each_entry(cur, qom_list, qom_list) { -+ if (team_queue_override_port_has_gt_prio_than(port, cur)) -+ break; -+ node = &cur->qom_list; -+ } -+ list_add_tail_rcu(&port->qom_list, node); -+} -+ -+static void __team_queue_override_enabled_check(struct team *team) -+{ -+ struct team_port *port; -+ bool enabled = false; -+ -+ list_for_each_entry(port, &team->port_list, list) { -+ if (!list_empty(&port->qom_list)) { -+ enabled = true; -+ break; -+ } -+ } -+ if (enabled == team->queue_override_enabled) -+ return; -+ netdev_dbg(team->dev, "%s queue override\n", -+ enabled ? "Enabling" : "Disabling"); -+ team->queue_override_enabled = enabled; -+} -+ -+static void team_queue_override_port_refresh(struct team *team, -+ struct team_port *port) -+{ -+ __team_queue_override_port_del(team, port); -+ __team_queue_override_port_add(team, port); -+ __team_queue_override_enabled_check(team); -+} -+ -+ - /**************** - * Port handling - ****************/ -@@ -688,6 +804,7 @@ static void team_port_enable(struct team *team, - hlist_add_head_rcu(&port->hlist, - team_port_index_hash(team, port->index)); - team_adjust_ops(team); -+ team_queue_override_port_refresh(team, port); - if (team->ops.port_enabled) - team->ops.port_enabled(team, port); - } -@@ -716,6 +833,7 @@ static void team_port_disable(struct team *team, - hlist_del_rcu(&port->hlist); - __reconstruct_port_hlist(team, port->index); - port->index = -1; -+ team_queue_override_port_refresh(team, port); - __team_adjust_ops(team, team->en_port_count - 1); - /* - * Wait until readers see adjusted ops. This ensures that -@@ -881,6 +999,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) - - port->dev = port_dev; - port->team = team; -+ INIT_LIST_HEAD(&port->qom_list); - - port->orig.mtu = port_dev->mtu; - err = dev_set_mtu(port_dev, dev->mtu); -@@ -1092,6 +1211,49 @@ static int team_user_linkup_en_option_set(struct team *team, - return 0; - } - -+static int team_priority_option_get(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ struct team_port *port = ctx->info->port; -+ -+ ctx->data.s32_val = port->priority; -+ return 0; -+} -+ -+static int team_priority_option_set(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ struct team_port *port = ctx->info->port; -+ -+ port->priority = ctx->data.s32_val; -+ team_queue_override_port_refresh(team, port); -+ return 0; -+} -+ -+static int team_queue_id_option_get(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ struct team_port *port = ctx->info->port; -+ -+ ctx->data.u32_val = port->queue_id; -+ return 0; -+} -+ -+static int team_queue_id_option_set(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ struct team_port *port = ctx->info->port; -+ -+ if (port->queue_id == ctx->data.u32_val) -+ return 0; -+ if (ctx->data.u32_val >= team->dev->real_num_tx_queues) -+ return -EINVAL; -+ port->queue_id = ctx->data.u32_val; -+ team_queue_override_port_refresh(team, port); -+ return 0; -+} -+ -+ - static const struct team_option team_options[] = { - { - .name = "mode", -@@ -1120,6 +1282,20 @@ static const struct team_option team_options[] = { - .getter = team_user_linkup_en_option_get, - .setter = team_user_linkup_en_option_set, - }, -+ { -+ .name = "priority", -+ .type = TEAM_OPTION_TYPE_S32, -+ .per_port = true, -+ .getter = team_priority_option_get, -+ .setter = team_priority_option_set, -+ }, -+ { -+ .name = "queue_id", -+ .type = TEAM_OPTION_TYPE_U32, -+ .per_port = true, -+ .getter = team_queue_id_option_get, -+ .setter = team_queue_id_option_set, -+ }, - }; - - static struct lock_class_key team_netdev_xmit_lock_key; -@@ -1155,6 +1331,9 @@ static int team_init(struct net_device *dev) - for (i = 0; i < TEAM_PORT_HASHENTRIES; i++) - INIT_HLIST_HEAD(&team->en_port_hlist[i]); - INIT_LIST_HEAD(&team->port_list); -+ err = team_queue_override_init(team); -+ if (err) -+ goto err_team_queue_override_init; - - team_adjust_ops(team); - -@@ -1170,6 +1349,8 @@ static int team_init(struct net_device *dev) - return 0; - - err_options_register: -+ team_queue_override_fini(team); -+err_team_queue_override_init: - free_percpu(team->pcpu_stats); - - return err; -@@ -1187,6 +1368,7 @@ static void team_uninit(struct net_device *dev) - - __team_change_mode(team, NULL); /* cleanup */ - __team_options_unregister(team, team_options, ARRAY_SIZE(team_options)); -+ team_queue_override_fini(team); - mutex_unlock(&team->lock); - } - -@@ -1216,10 +1398,12 @@ static int team_close(struct net_device *dev) - static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct team *team = netdev_priv(dev); -- bool tx_success = false; -+ bool tx_success; - unsigned int len = skb->len; - -- tx_success = team->ops.transmit(team, skb); -+ tx_success = team_queue_override_transmit(team, skb); -+ if (!tx_success) -+ tx_success = team->ops.transmit(team, skb); - if (tx_success) { - struct team_pcpu_stats *pcpu_stats; - -@@ -1787,6 +1971,12 @@ static int team_nl_fill_one_option_get(struct sk_buff *skb, struct team *team, - nla_put_flag(skb, TEAM_ATTR_OPTION_DATA)) - goto nest_cancel; - break; -+ case TEAM_OPTION_TYPE_S32: -+ if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_S32)) -+ goto nest_cancel; -+ if (nla_put_s32(skb, TEAM_ATTR_OPTION_DATA, ctx.data.s32_val)) -+ goto nest_cancel; -+ break; - default: - BUG(); - } -@@ -1975,6 +2165,9 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - case NLA_FLAG: - opt_type = TEAM_OPTION_TYPE_BOOL; - break; -+ case NLA_S32: -+ opt_type = TEAM_OPTION_TYPE_S32; -+ break; - default: - goto team_put; - } -@@ -2031,6 +2224,9 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - case TEAM_OPTION_TYPE_BOOL: - ctx.data.bool_val = attr_data ? true : false; - break; -+ case TEAM_OPTION_TYPE_S32: -+ ctx.data.s32_val = nla_get_s32(attr_data); -+ break; - default: - BUG(); - } -diff --git a/include/linux/if_team.h b/include/linux/if_team.h -index 6960fc1..33fcc20 100644 ---- a/include/linux/if_team.h -+++ b/include/linux/if_team.h -@@ -67,6 +67,9 @@ struct team_port { - struct netpoll *np; - #endif - -+ s32 priority; /* lower number ~ higher priority */ -+ u16 queue_id; -+ struct list_head qom_list; /* node in queue override mapping list */ - long mode_priv[0]; - }; - -@@ -130,6 +133,7 @@ enum team_option_type { - TEAM_OPTION_TYPE_STRING, - TEAM_OPTION_TYPE_BINARY, - TEAM_OPTION_TYPE_BOOL, -+ TEAM_OPTION_TYPE_S32, - }; - - struct team_option_inst_info { -@@ -146,6 +150,7 @@ struct team_gsetter_ctx { - u32 len; - } bin_val; - bool bool_val; -+ s32 s32_val; - } data; - struct team_option_inst_info *info; - }; -@@ -197,6 +202,8 @@ struct team { - - const struct team_mode *mode; - struct team_mode_ops ops; -+ bool queue_override_enabled; -+ struct list_head *qom_lists; /* array of queue override mapping lists */ - long mode_priv[TEAM_MODE_PRIV_LONGS]; - }; - -diff --git a/include/net/netlink.h b/include/net/netlink.h -index 785f37a..09175d5 100644 ---- a/include/net/netlink.h -+++ b/include/net/netlink.h -@@ -98,6 +98,10 @@ - * nla_put_u16(skb, type, value) add u16 attribute to skb - * nla_put_u32(skb, type, value) add u32 attribute to skb - * nla_put_u64(skb, type, value) add u64 attribute to skb -+ * nla_put_s8(skb, type, value) add s8 attribute to skb -+ * nla_put_s16(skb, type, value) add s16 attribute to skb -+ * nla_put_s32(skb, type, value) add s32 attribute to skb -+ * nla_put_s64(skb, type, value) add s64 attribute to skb - * nla_put_string(skb, type, str) add string attribute to skb - * nla_put_flag(skb, type) add flag attribute to skb - * nla_put_msecs(skb, type, jiffies) add msecs attribute to skb -@@ -121,6 +125,10 @@ - * nla_get_u16(nla) get payload for a u16 attribute - * nla_get_u32(nla) get payload for a u32 attribute - * nla_get_u64(nla) get payload for a u64 attribute -+ * nla_get_s8(nla) get payload for a s8 attribute -+ * nla_get_s16(nla) get payload for a s16 attribute -+ * nla_get_s32(nla) get payload for a s32 attribute -+ * nla_get_s64(nla) get payload for a s64 attribute - * nla_get_flag(nla) return 1 if flag is true - * nla_get_msecs(nla) get payload for a msecs attribute - * -@@ -160,6 +168,10 @@ enum { - NLA_NESTED_COMPAT, - NLA_NUL_STRING, - NLA_BINARY, -+ NLA_S8, -+ NLA_S16, -+ NLA_S32, -+ NLA_S64, - __NLA_TYPE_MAX, - }; - -@@ -183,6 +195,8 @@ enum { - * NLA_NESTED_COMPAT Minimum length of structure payload - * NLA_U8, NLA_U16, - * NLA_U32, NLA_U64, -+ * NLA_S8, NLA_S16, -+ * NLA_S32, NLA_S64, - * NLA_MSECS Leaving the length field zero will verify the - * given type fits, using it verifies minimum length - * just like "All other" -@@ -879,6 +893,50 @@ static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value) - } - - /** -+ * nla_put_s8 - Add a s8 netlink attribute to a socket buffer -+ * @skb: socket buffer to add attribute to -+ * @attrtype: attribute type -+ * @value: numeric value -+ */ -+static inline int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value) -+{ -+ return nla_put(skb, attrtype, sizeof(s8), &value); -+} -+ -+/** -+ * nla_put_s16 - Add a s16 netlink attribute to a socket buffer -+ * @skb: socket buffer to add attribute to -+ * @attrtype: attribute type -+ * @value: numeric value -+ */ -+static inline int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value) -+{ -+ return nla_put(skb, attrtype, sizeof(s16), &value); -+} -+ -+/** -+ * nla_put_s32 - Add a s32 netlink attribute to a socket buffer -+ * @skb: socket buffer to add attribute to -+ * @attrtype: attribute type -+ * @value: numeric value -+ */ -+static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value) -+{ -+ return nla_put(skb, attrtype, sizeof(s32), &value); -+} -+ -+/** -+ * nla_put_s64 - Add a s64 netlink attribute to a socket buffer -+ * @skb: socket buffer to add attribute to -+ * @attrtype: attribute type -+ * @value: numeric value -+ */ -+static inline int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value) -+{ -+ return nla_put(skb, attrtype, sizeof(s64), &value); -+} -+ -+/** - * nla_put_string - Add a string netlink attribute to a socket buffer - * @skb: socket buffer to add attribute to - * @attrtype: attribute type -@@ -994,6 +1052,46 @@ static inline __be64 nla_get_be64(const struct nlattr *nla) - } - - /** -+ * nla_get_s32 - return payload of s32 attribute -+ * @nla: s32 netlink attribute -+ */ -+static inline s32 nla_get_s32(const struct nlattr *nla) -+{ -+ return *(s32 *) nla_data(nla); -+} -+ -+/** -+ * nla_get_s16 - return payload of s16 attribute -+ * @nla: s16 netlink attribute -+ */ -+static inline s16 nla_get_s16(const struct nlattr *nla) -+{ -+ return *(s16 *) nla_data(nla); -+} -+ -+/** -+ * nla_get_s8 - return payload of s8 attribute -+ * @nla: s8 netlink attribute -+ */ -+static inline s8 nla_get_s8(const struct nlattr *nla) -+{ -+ return *(s8 *) nla_data(nla); -+} -+ -+/** -+ * nla_get_s64 - return payload of s64 attribute -+ * @nla: s64 netlink attribute -+ */ -+static inline s64 nla_get_s64(const struct nlattr *nla) -+{ -+ s64 tmp; -+ -+ nla_memcpy(&tmp, nla, sizeof(tmp)); -+ -+ return tmp; -+} -+ -+/** - * nla_get_flag - return payload of flag attribute - * @nla: flag netlink attribute - */ - diff --git a/freed-ora/current/f18/team-net-next-20121205.patch b/freed-ora/current/f18/team-net-next-20121205.patch deleted file mode 100644 index 51249f9c1..000000000 --- a/freed-ora/current/f18/team-net-next-20121205.patch +++ /dev/null @@ -1,60 +0,0 @@ - -Backport fixes from linus's tree. - -upstream commits backported: -commit 403f43c937d24832b18524f65415c0bbba6b5064 - team: bcast: convert return value of team_dev_queue_xmit() to bool correctly -commit 3ed7147189d2fbe8ac6da95db2fd9d6d52f53ce9 - team: fix hw_features setup - -Signed-off-by: Jiri Pirko <jpirko@redhat.com> ---- - drivers/net/team/team.c | 4 +++- - drivers/net/team/team_mode_broadcast.c | 6 +++--- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 5d8e1cb..f504773 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -1792,10 +1792,12 @@ static void team_setup(struct net_device *dev) - - dev->features |= NETIF_F_LLTX; - dev->features |= NETIF_F_GRO; -- dev->hw_features = NETIF_F_HW_VLAN_TX | -+ dev->hw_features = TEAM_VLAN_FEATURES | -+ NETIF_F_HW_VLAN_TX | - NETIF_F_HW_VLAN_RX | - NETIF_F_HW_VLAN_FILTER; - -+ dev->hw_features &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_HW_CSUM); - dev->features |= dev->hw_features; - } - -diff --git a/drivers/net/team/team_mode_broadcast.c b/drivers/net/team/team_mode_broadcast.c -index 9db0171..c5db428 100644 ---- a/drivers/net/team/team_mode_broadcast.c -+++ b/drivers/net/team/team_mode_broadcast.c -@@ -29,8 +29,8 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) - if (last) { - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2) { -- ret = team_dev_queue_xmit(team, last, -- skb2); -+ ret = !team_dev_queue_xmit(team, last, -+ skb2); - if (!sum_ret) - sum_ret = ret; - } -@@ -39,7 +39,7 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) - } - } - if (last) { -- ret = team_dev_queue_xmit(team, last, skb); -+ ret = !team_dev_queue_xmit(team, last, skb); - if (!sum_ret) - sum_ret = ret; - } --- -1.7.11.7 - diff --git a/freed-ora/current/f18/team-net-next-update-20120927.patch b/freed-ora/current/f18/team-net-next-update-20120927.patch deleted file mode 100644 index a61311619..000000000 --- a/freed-ora/current/f18/team-net-next-update-20120927.patch +++ /dev/null @@ -1,335 +0,0 @@ ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/drivers/net/team/Kconfig -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/drivers/net/team/Kconfig -@@ -21,7 +21,7 @@ config NET_TEAM_MODE_BROADCAST - ---help--- - Basic mode where packets are transmitted always by all suitable ports. - -- All added ports are setup to have team's mac address. -+ All added ports are setup to have team's device address. - - To compile this team mode as a module, choose M here: the module - will be called team_mode_broadcast. -@@ -33,7 +33,7 @@ config NET_TEAM_MODE_ROUNDROBIN - Basic mode where port used for transmitting packets is selected in - round-robin fashion using packet counter. - -- All added ports are setup to have team's mac address. -+ All added ports are setup to have team's device address. - - To compile this team mode as a module, choose M here: the module - will be called team_mode_roundrobin. ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/drivers/net/team/team.c -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/drivers/net/team/team.c -@@ -54,29 +54,29 @@ static struct team_port *team_port_get_r - } - - /* -- * Since the ability to change mac address for open port device is tested in -+ * Since the ability to change device address for open port device is tested in - * team_port_add, this function can be called without control of return value - */ --static int __set_port_mac(struct net_device *port_dev, -- const unsigned char *dev_addr) -+static int __set_port_dev_addr(struct net_device *port_dev, -+ const unsigned char *dev_addr) - { - struct sockaddr addr; - -- memcpy(addr.sa_data, dev_addr, ETH_ALEN); -- addr.sa_family = ARPHRD_ETHER; -+ memcpy(addr.sa_data, dev_addr, port_dev->addr_len); -+ addr.sa_family = port_dev->type; - return dev_set_mac_address(port_dev, &addr); - } - --static int team_port_set_orig_mac(struct team_port *port) -+static int team_port_set_orig_dev_addr(struct team_port *port) - { -- return __set_port_mac(port->dev, port->orig.dev_addr); -+ return __set_port_dev_addr(port->dev, port->orig.dev_addr); - } - --int team_port_set_team_mac(struct team_port *port) -+int team_port_set_team_dev_addr(struct team_port *port) - { -- return __set_port_mac(port->dev, port->team->dev->dev_addr); -+ return __set_port_dev_addr(port->dev, port->team->dev->dev_addr); - } --EXPORT_SYMBOL(team_port_set_team_mac); -+EXPORT_SYMBOL(team_port_set_team_dev_addr); - - static void team_refresh_port_linkup(struct team_port *port) - { -@@ -967,6 +967,8 @@ static struct netpoll_info *team_netpoll - #endif - - static void __team_port_change_port_added(struct team_port *port, bool linkup); -+static int team_dev_type_check_change(struct net_device *dev, -+ struct net_device *port_dev); - - static int team_port_add(struct team *team, struct net_device *port_dev) - { -@@ -975,9 +977,8 @@ static int team_port_add(struct team *te - char *portname = port_dev->name; - int err; - -- if (port_dev->flags & IFF_LOOPBACK || -- port_dev->type != ARPHRD_ETHER) { -- netdev_err(dev, "Device %s is of an unsupported type\n", -+ if (port_dev->flags & IFF_LOOPBACK) { -+ netdev_err(dev, "Device %s is loopback device. Loopback devices can't be added as a team port\n", - portname); - return -EINVAL; - } -@@ -988,6 +989,17 @@ static int team_port_add(struct team *te - return -EBUSY; - } - -+ if (port_dev->features & NETIF_F_VLAN_CHALLENGED && -+ vlan_uses_dev(dev)) { -+ netdev_err(dev, "Device %s is VLAN challenged and team device has VLAN set up\n", -+ portname); -+ return -EPERM; -+ } -+ -+ err = team_dev_type_check_change(dev, port_dev); -+ if (err) -+ return err; -+ - if (port_dev->flags & IFF_UP) { - netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n", - portname); -@@ -1010,7 +1022,7 @@ static int team_port_add(struct team *te - goto err_set_mtu; - } - -- memcpy(port->orig.dev_addr, port_dev->dev_addr, ETH_ALEN); -+ memcpy(port->orig.dev_addr, port_dev->dev_addr, port_dev->addr_len); - - err = team_port_enter(team, port); - if (err) { -@@ -1091,7 +1103,7 @@ err_vids_add: - - err_dev_open: - team_port_leave(team, port); -- team_port_set_orig_mac(port); -+ team_port_set_orig_dev_addr(port); - - err_port_enter: - dev_set_mtu(port_dev, port->orig.mtu); -@@ -1129,7 +1141,7 @@ static int team_port_del(struct team *te - vlan_vids_del_by_dev(port_dev, dev); - dev_close(port_dev); - team_port_leave(team, port); -- team_port_set_orig_mac(port); -+ team_port_set_orig_dev_addr(port); - dev_set_mtu(port_dev, port->orig.mtu); - synchronize_rcu(); - kfree(port); -@@ -1480,17 +1492,18 @@ static void team_set_rx_mode(struct net_ - - static int team_set_mac_address(struct net_device *dev, void *p) - { -+ struct sockaddr *addr = p; - struct team *team = netdev_priv(dev); - struct team_port *port; -- int err; - -- err = eth_mac_addr(dev, p); -- if (err) -- return err; -+ if (dev->type == ARPHRD_ETHER && !is_valid_ether_addr(addr->sa_data)) -+ return -EADDRNOTAVAIL; -+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); -+ dev->addr_assign_type &= ~NET_ADDR_RANDOM; - rcu_read_lock(); - list_for_each_entry_rcu(port, &team->port_list, list) -- if (team->ops.port_change_mac) -- team->ops.port_change_mac(team, port); -+ if (team->ops.port_change_dev_addr) -+ team->ops.port_change_dev_addr(team, port); - rcu_read_unlock(); - return 0; - } -@@ -1721,6 +1734,45 @@ static const struct net_device_ops team_ - * rt netlink interface - ***********************/ - -+static void team_setup_by_port(struct net_device *dev, -+ struct net_device *port_dev) -+{ -+ dev->header_ops = port_dev->header_ops; -+ dev->type = port_dev->type; -+ dev->hard_header_len = port_dev->hard_header_len; -+ dev->addr_len = port_dev->addr_len; -+ dev->mtu = port_dev->mtu; -+ memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len); -+ memcpy(dev->dev_addr, port_dev->dev_addr, port_dev->addr_len); -+ dev->addr_assign_type &= ~NET_ADDR_RANDOM; -+} -+ -+static int team_dev_type_check_change(struct net_device *dev, -+ struct net_device *port_dev) -+{ -+ struct team *team = netdev_priv(dev); -+ char *portname = port_dev->name; -+ int err; -+ -+ if (dev->type == port_dev->type) -+ return 0; -+ if (!list_empty(&team->port_list)) { -+ netdev_err(dev, "Device %s is of different type\n", portname); -+ return -EBUSY; -+ } -+ err = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, dev); -+ err = notifier_to_errno(err); -+ if (err) { -+ netdev_err(dev, "Refused to change device type\n"); -+ return err; -+ } -+ dev_uc_flush(dev); -+ dev_mc_flush(dev); -+ team_setup_by_port(dev, port_dev); -+ call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev); -+ return 0; -+} -+ - static void team_setup(struct net_device *dev) - { - ether_setup(dev); -@@ -2442,7 +2494,7 @@ static void __team_options_change_check( - list_add_tail(&opt_inst->tmp_list, &sel_opt_inst_list); - } - err = team_nl_send_event_options_get(team, &sel_opt_inst_list); -- if (err) -+ if (err && err != -ESRCH) - netdev_warn(team->dev, "Failed to send options change via netlink (err %d)\n", - err); - } -@@ -2471,9 +2523,9 @@ static void __team_port_change_send(stru - - send_event: - err = team_nl_send_event_port_list_get(port->team); -- if (err) -- netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n", -- port->dev->name); -+ if (err && err != -ESRCH) -+ netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink (err %d)\n", -+ port->dev->name, err); - - } - ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/drivers/net/team/team_mode_broadcast.c -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/drivers/net/team/team_mode_broadcast.c -@@ -48,18 +48,18 @@ static bool bc_transmit(struct team *tea - - static int bc_port_enter(struct team *team, struct team_port *port) - { -- return team_port_set_team_mac(port); -+ return team_port_set_team_dev_addr(port); - } - --static void bc_port_change_mac(struct team *team, struct team_port *port) -+static void bc_port_change_dev_addr(struct team *team, struct team_port *port) - { -- team_port_set_team_mac(port); -+ team_port_set_team_dev_addr(port); - } - - static const struct team_mode_ops bc_mode_ops = { - .transmit = bc_transmit, - .port_enter = bc_port_enter, -- .port_change_mac = bc_port_change_mac, -+ .port_change_dev_addr = bc_port_change_dev_addr, - }; - - static const struct team_mode bc_mode = { ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/drivers/net/team/team_mode_roundrobin.c -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/drivers/net/team/team_mode_roundrobin.c -@@ -66,18 +66,18 @@ drop: - - static int rr_port_enter(struct team *team, struct team_port *port) - { -- return team_port_set_team_mac(port); -+ return team_port_set_team_dev_addr(port); - } - --static void rr_port_change_mac(struct team *team, struct team_port *port) -+static void rr_port_change_dev_addr(struct team *team, struct team_port *port) - { -- team_port_set_team_mac(port); -+ team_port_set_team_dev_addr(port); - } - - static const struct team_mode_ops rr_mode_ops = { - .transmit = rr_transmit, - .port_enter = rr_port_enter, -- .port_change_mac = rr_port_change_mac, -+ .port_change_dev_addr = rr_port_change_dev_addr, - }; - - static const struct team_mode rr_mode = { ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/include/linux/if_team.h -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/include/linux/if_team.h -@@ -108,7 +108,7 @@ struct team_mode_ops { - bool (*transmit)(struct team *team, struct sk_buff *skb); - int (*port_enter)(struct team *team, struct team_port *port); - void (*port_leave)(struct team *team, struct team_port *port); -- void (*port_change_mac)(struct team *team, struct team_port *port); -+ void (*port_change_dev_addr)(struct team *team, struct team_port *port); - void (*port_enabled)(struct team *team, struct team_port *port); - void (*port_disabled)(struct team *team, struct team_port *port); - }; -@@ -238,7 +238,7 @@ static inline struct team_port *team_get - return NULL; - } - --extern int team_port_set_team_mac(struct team_port *port); -+extern int team_port_set_team_dev_addr(struct team_port *port); - extern int team_options_register(struct team *team, - const struct team_option *option, - size_t option_count); ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/include/linux/if_vlan.h -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/include/linux/if_vlan.h -@@ -74,8 +74,6 @@ static inline struct vlan_ethhdr *vlan_e - /* found in socket.c */ - extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *)); - --struct vlan_info; -- - static inline int is_vlan_dev(struct net_device *dev) - { - return dev->priv_flags & IFF_802_1Q_VLAN; -@@ -101,6 +99,8 @@ extern int vlan_vids_add_by_dev(struct n - const struct net_device *by_dev); - extern void vlan_vids_del_by_dev(struct net_device *dev, - const struct net_device *by_dev); -+ -+extern bool vlan_uses_dev(const struct net_device *dev); - #else - static inline struct net_device * - __vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) -@@ -151,6 +151,11 @@ static inline void vlan_vids_del_by_dev( - const struct net_device *by_dev) - { - } -+ -+static inline bool vlan_uses_dev(const struct net_device *dev) -+{ -+ return false; -+} - #endif - - /** ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/net/8021q/vlan_core.c -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/net/8021q/vlan_core.c -@@ -368,3 +368,9 @@ void vlan_vids_del_by_dev(struct net_dev - vlan_vid_del(dev, vid_info->vid); - } - EXPORT_SYMBOL(vlan_vids_del_by_dev); -+ -+bool vlan_uses_dev(const struct net_device *dev) -+{ -+ return rtnl_dereference(dev->vlan_info) ? true : false; -+} -+EXPORT_SYMBOL(vlan_uses_dev); diff --git a/freed-ora/current/f18/uprobes-upstream-backport.patch b/freed-ora/current/f18/uprobes-upstream-backport.patch deleted file mode 100644 index 9614e41b9..000000000 --- a/freed-ora/current/f18/uprobes-upstream-backport.patch +++ /dev/null @@ -1,1376 +0,0 @@ -Hello, - -Test builds: - f18: http://koji.fedoraproject.org/koji/taskinfo?taskID=4635065 - f17: http://koji.fedoraproject.org/koji/taskinfo?taskID=4635062 - -The split-out series is available in the git repository at: - http://fedorapeople.org/cgit/aarapov/public_git/kernel-uprobes.git - -Just <at> jistone's patch is not upstream that exports functions. -Yes, I know it must go to upstream. :-) I will try to do what I can before -the next uprobes update. - ---------------------------------------------------------------- -Josh Stone (1): - uprobes: add exports necessary for uprobes use by modules - -Oleg Nesterov (35): - uprobes: Kill uprobes_state->count - uprobes: Kill dup_mmap()->uprobe_mmap(), simplify uprobe_mmap/munmap - uprobes: Change uprobe_mmap() to ignore the errors but check fatal_signal_pending() - uprobes: Do not use -EEXIST in install_breakpoint() paths - uprobes: Introduce MMF_HAS_UPROBES - uprobes: Fold uprobe_reset_state() into uprobe_dup_mmap() - uprobes: Remove "verify" argument from set_orig_insn() - uprobes: uprobes_treelock should not disable irqs - uprobes: Introduce MMF_RECALC_UPROBES - uprobes: Teach find_active_uprobe() to clear MMF_HAS_UPROBES - ptrace/x86: Introduce set_task_blockstep() helper - ptrace/x86: Partly fix set_task_blockstep()->update_debugctlmsr() logic - uprobes/x86: Do not (ab)use TIF_SINGLESTEP/user_*_single_step() for single-stepping - uprobes/x86: Xol should send SIGTRAP if X86_EFLAGS_TF was set - uprobes/x86: Fix arch_uprobe_disable_step() && UTASK_SSTEP_TRAPPED interaction - uprobes: Make arch_uprobe_task->saved_trap_nr "unsigned int" - uprobes: Do not leak UTASK_BP_HIT if find_active_uprobe() fails - uprobes: Do not setup ->active_uprobe/state prematurely - uprobes: Fix UPROBE_SKIP_SSTEP checks in handle_swbp() - uprobes: Kill UTASK_BP_HIT state - uprobes: Move clear_thread_flag(TIF_UPROBE) to uprobe_notify_resume() - uprobes: Change write_opcode() to use FOLL_FORCE - uprobes: Change valid_vma() to demand VM_MAYEXEC rather than VM_EXEC - uprobes: Restrict valid_vma(false) to skip VM_SHARED vmas - uprobes: Kill set_swbp()->is_swbp_at_addr() - uprobes: Introduce copy_opcode(), kill read_opcode() - uprobes: Kill set_orig_insn()->is_swbp_at_addr() - uprobes: Simplify is_swbp_at_addr(), remove stale comments - uprobes/x86: Only rep+nop can be emulated correctly - uprobes: Don't return success if alloc_uprobe() fails - uprobes: Do not delete uprobe if uprobe_unregister() fails - uprobes: Fix handle_swbp() vs unregister() + register() race - uprobes: Introduce prepare_uprobe() - uprobes: Fix prepare_uprobe() race with itself - uprobes: Fix the racy uprobe->flags manipulation - -Sebastian Andrzej Siewior (4): - uprobes: Remove check for uprobe variable in handle_swbp() - uprobes: Don't put NULL pointer in uprobe_register() - uprobes: Introduce arch_uprobe_enable/disable_step() - uprobes/x86: Implement x86 specific arch_uprobe_*_step - -Srikar Dronamraju (1): - uprobes: Remove redundant lock_page/unlock_page - - arch/x86/include/asm/processor.h | 2 + - arch/x86/include/asm/uprobes.h | 3 +- - arch/x86/kernel/signal.c | 4 +- - arch/x86/kernel/step.c | 53 ++-- - arch/x86/kernel/uprobes.c | 64 ++++- - include/linux/sched.h | 3 + - include/linux/uprobes.h | 26 +- - kernel/events/uprobes.c | 564 ++++++++++++++++++--------------------- - kernel/fork.c | 6 +- - kernel/ptrace.c | 6 + - 10 files changed, 375 insertions(+), 356 deletions(-) - -diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h -index d048cad..433d2e5 100644 ---- a/arch/x86/include/asm/processor.h -+++ b/arch/x86/include/asm/processor.h -@@ -759,6 +759,8 @@ static inline void update_debugctlmsr(unsigned long debugctlmsr) - wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr); - } - -+extern void set_task_blockstep(struct task_struct *task, bool on); -+ - /* - * from system description table in BIOS. Mostly for MCA use, but - * others may find it useful: -diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h -index f3971bb..8ff8be7 100644 ---- a/arch/x86/include/asm/uprobes.h -+++ b/arch/x86/include/asm/uprobes.h -@@ -42,10 +42,11 @@ struct arch_uprobe { - }; - - struct arch_uprobe_task { -- unsigned long saved_trap_nr; - #ifdef CONFIG_X86_64 - unsigned long saved_scratch_register; - #endif -+ unsigned int saved_trap_nr; -+ unsigned int saved_tf; - }; - - extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); -diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c -index b280908..0041e5a 100644 ---- a/arch/x86/kernel/signal.c -+++ b/arch/x86/kernel/signal.c -@@ -785,10 +785,8 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) - mce_notify_process(); - #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ - -- if (thread_info_flags & _TIF_UPROBE) { -- clear_thread_flag(TIF_UPROBE); -+ if (thread_info_flags & _TIF_UPROBE) - uprobe_notify_resume(regs); -- } - - /* deal with pending signal delivery */ - if (thread_info_flags & _TIF_SIGPENDING) -diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c -index c346d11..cd3b243 100644 ---- a/arch/x86/kernel/step.c -+++ b/arch/x86/kernel/step.c -@@ -157,6 +157,33 @@ static int enable_single_step(struct task_struct *child) - return 1; - } - -+void set_task_blockstep(struct task_struct *task, bool on) -+{ -+ unsigned long debugctl; -+ -+ /* -+ * Ensure irq/preemption can't change debugctl in between. -+ * Note also that both TIF_BLOCKSTEP and debugctl should -+ * be changed atomically wrt preemption. -+ * FIXME: this means that set/clear TIF_BLOCKSTEP is simply -+ * wrong if task != current, SIGKILL can wakeup the stopped -+ * tracee and set/clear can play with the running task, this -+ * can confuse the next __switch_to_xtra(). -+ */ -+ local_irq_disable(); -+ debugctl = get_debugctlmsr(); -+ if (on) { -+ debugctl |= DEBUGCTLMSR_BTF; -+ set_tsk_thread_flag(task, TIF_BLOCKSTEP); -+ } else { -+ debugctl &= ~DEBUGCTLMSR_BTF; -+ clear_tsk_thread_flag(task, TIF_BLOCKSTEP); -+ } -+ if (task == current) -+ update_debugctlmsr(debugctl); -+ local_irq_enable(); -+} -+ - /* - * Enable single or block step. - */ -@@ -169,19 +196,10 @@ static void enable_step(struct task_struct *child, bool block) - * So no one should try to use debugger block stepping in a program - * that uses user-mode single stepping itself. - */ -- if (enable_single_step(child) && block) { -- unsigned long debugctl = get_debugctlmsr(); -- -- debugctl |= DEBUGCTLMSR_BTF; -- update_debugctlmsr(debugctl); -- set_tsk_thread_flag(child, TIF_BLOCKSTEP); -- } else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { -- unsigned long debugctl = get_debugctlmsr(); -- -- debugctl &= ~DEBUGCTLMSR_BTF; -- update_debugctlmsr(debugctl); -- clear_tsk_thread_flag(child, TIF_BLOCKSTEP); -- } -+ if (enable_single_step(child) && block) -+ set_task_blockstep(child, true); -+ else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) -+ set_task_blockstep(child, false); - } - - void user_enable_single_step(struct task_struct *child) -@@ -199,13 +217,8 @@ void user_disable_single_step(struct task_struct *child) - /* - * Make sure block stepping (BTF) is disabled. - */ -- if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { -- unsigned long debugctl = get_debugctlmsr(); -- -- debugctl &= ~DEBUGCTLMSR_BTF; -- update_debugctlmsr(debugctl); -- clear_tsk_thread_flag(child, TIF_BLOCKSTEP); -- } -+ if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) -+ set_task_blockstep(child, false); - - /* Always clear TIF_SINGLESTEP... */ - clear_tsk_thread_flag(child, TIF_SINGLESTEP); -diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c -index 36fd420..aafa555 100644 ---- a/arch/x86/kernel/uprobes.c -+++ b/arch/x86/kernel/uprobes.c -@@ -41,6 +41,9 @@ - /* Adjust the return address of a call insn */ - #define UPROBE_FIX_CALL 0x2 - -+/* Instruction will modify TF, don't change it */ -+#define UPROBE_FIX_SETF 0x4 -+ - #define UPROBE_FIX_RIP_AX 0x8000 - #define UPROBE_FIX_RIP_CX 0x4000 - -@@ -239,6 +242,10 @@ static void prepare_fixups(struct arch_uprobe *auprobe, struct insn *insn) - insn_get_opcode(insn); /* should be a nop */ - - switch (OPCODE1(insn)) { -+ case 0x9d: -+ /* popf */ -+ auprobe->fixups |= UPROBE_FIX_SETF; -+ break; - case 0xc3: /* ret/lret */ - case 0xcb: - case 0xc2: -@@ -644,32 +651,63 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) - - /* - * Skip these instructions as per the currently known x86 ISA. -- * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 } -+ * rep=0x66*; nop=0x90 - */ --bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) -+static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) - { - int i; - - for (i = 0; i < MAX_UINSN_BYTES; i++) { -- if ((auprobe->insn[i] == 0x66)) -+ if (auprobe->insn[i] == 0x66) - continue; - - if (auprobe->insn[i] == 0x90) - return true; - -- if (i == (MAX_UINSN_BYTES - 1)) -- break; -+ break; -+ } -+ return false; -+} - -- if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x1f)) -- return true; -+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) -+{ -+ bool ret = __skip_sstep(auprobe, regs); -+ if (ret && (regs->flags & X86_EFLAGS_TF)) -+ send_sig(SIGTRAP, current, 0); -+ return ret; -+} - -- if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x19)) -- return true; -+void arch_uprobe_enable_step(struct arch_uprobe *auprobe) -+{ -+ struct task_struct *task = current; -+ struct arch_uprobe_task *autask = &task->utask->autask; -+ struct pt_regs *regs = task_pt_regs(task); - -- if ((auprobe->insn[i] == 0x87) && (auprobe->insn[i+1] == 0xc0)) -- return true; -+ autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF); - -- break; -+ regs->flags |= X86_EFLAGS_TF; -+ if (test_tsk_thread_flag(task, TIF_BLOCKSTEP)) -+ set_task_blockstep(task, false); -+} -+ -+void arch_uprobe_disable_step(struct arch_uprobe *auprobe) -+{ -+ struct task_struct *task = current; -+ struct arch_uprobe_task *autask = &task->utask->autask; -+ bool trapped = (task->utask->state == UTASK_SSTEP_TRAPPED); -+ struct pt_regs *regs = task_pt_regs(task); -+ /* -+ * The state of TIF_BLOCKSTEP was not saved so we can get an extra -+ * SIGTRAP if we do not clear TF. We need to examine the opcode to -+ * make it right. -+ */ -+ if (unlikely(trapped)) { -+ if (!autask->saved_tf) -+ regs->flags &= ~X86_EFLAGS_TF; -+ } else { -+ if (autask->saved_tf) -+ send_sig(SIGTRAP, task, 0); -+ else if (!(auprobe->fixups & UPROBE_FIX_SETF)) -+ regs->flags &= ~X86_EFLAGS_TF; - } -- return false; - } -diff --git a/include/linux/sched.h b/include/linux/sched.h -index 23bddac..ba300be 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -446,6 +446,9 @@ extern int get_dumpable(struct mm_struct *mm); - #define MMF_VM_HUGEPAGE 17 /* set when VM_HUGEPAGE is set on vma */ - #define MMF_EXE_FILE_CHANGED 18 /* see prctl_set_mm_exe_file() */ - -+#define MMF_HAS_UPROBES 19 /* has uprobes */ -+#define MMF_RECALC_UPROBES 20 /* MMF_HAS_UPROBES can be wrong */ -+ - #define MMF_INIT_MASK (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK) - - struct sighand_struct { -diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h -index efe4b33..2459457 100644 ---- a/include/linux/uprobes.h -+++ b/include/linux/uprobes.h -@@ -35,16 +35,6 @@ struct inode; - # include <asm/uprobes.h> - #endif - --/* flags that denote/change uprobes behaviour */ -- --/* Have a copy of original instruction */ --#define UPROBE_COPY_INSN 0x1 -- --/* Dont run handlers when first register/ last unregister in progress*/ --#define UPROBE_RUN_HANDLER 0x2 --/* Can skip singlestep */ --#define UPROBE_SKIP_SSTEP 0x4 -- - struct uprobe_consumer { - int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs); - /* -@@ -59,7 +49,6 @@ struct uprobe_consumer { - #ifdef CONFIG_UPROBES - enum uprobe_task_state { - UTASK_RUNNING, -- UTASK_BP_HIT, - UTASK_SSTEP, - UTASK_SSTEP_ACK, - UTASK_SSTEP_TRAPPED, -@@ -99,25 +88,27 @@ struct xol_area { - - struct uprobes_state { - struct xol_area *xol_area; -- atomic_t count; - }; -+ - extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); --extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr, bool verify); -+extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); - extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); - extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); - extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); - extern int uprobe_mmap(struct vm_area_struct *vma); - extern void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end); -+extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm); - extern void uprobe_free_utask(struct task_struct *t); - extern void uprobe_copy_process(struct task_struct *t); - extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); -+extern void __weak arch_uprobe_enable_step(struct arch_uprobe *arch); -+extern void __weak arch_uprobe_disable_step(struct arch_uprobe *arch); - extern int uprobe_post_sstep_notifier(struct pt_regs *regs); - extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); - extern void uprobe_notify_resume(struct pt_regs *regs); - extern bool uprobe_deny_signal(void); - extern bool __weak arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs); - extern void uprobe_clear_state(struct mm_struct *mm); --extern void uprobe_reset_state(struct mm_struct *mm); - #else /* !CONFIG_UPROBES */ - struct uprobes_state { - }; -@@ -138,6 +129,10 @@ static inline void - uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) - { - } -+static inline void -+uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) -+{ -+} - static inline void uprobe_notify_resume(struct pt_regs *regs) - { - } -@@ -158,8 +153,5 @@ static inline void uprobe_copy_process(struct task_struct *t) - static inline void uprobe_clear_state(struct mm_struct *mm) - { - } --static inline void uprobe_reset_state(struct mm_struct *mm) --{ --} - #endif /* !CONFIG_UPROBES */ - #endif /* _LINUX_UPROBES_H */ -diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c -index c08a22d..e933f65 100644 ---- a/kernel/events/uprobes.c -+++ b/kernel/events/uprobes.c -@@ -27,6 +27,7 @@ - #include <linux/pagemap.h> /* read_mapping_page */ - #include <linux/slab.h> - #include <linux/sched.h> -+#include <linux/export.h> - #include <linux/rmap.h> /* anon_vma_prepare */ - #include <linux/mmu_notifier.h> /* set_pte_at_notify */ - #include <linux/swap.h> /* try_to_free_swap */ -@@ -78,15 +79,23 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ]; - */ - static atomic_t uprobe_events = ATOMIC_INIT(0); - -+/* Have a copy of original instruction */ -+#define UPROBE_COPY_INSN 0 -+/* Dont run handlers when first register/ last unregister in progress*/ -+#define UPROBE_RUN_HANDLER 1 -+/* Can skip singlestep */ -+#define UPROBE_SKIP_SSTEP 2 -+ - struct uprobe { - struct rb_node rb_node; /* node in the rb tree */ - atomic_t ref; - struct rw_semaphore consumer_rwsem; -+ struct mutex copy_mutex; /* TODO: kill me and UPROBE_COPY_INSN */ - struct list_head pending_list; - struct uprobe_consumer *consumers; - struct inode *inode; /* Also hold a ref to inode */ - loff_t offset; -- int flags; -+ unsigned long flags; - struct arch_uprobe arch; - }; - -@@ -100,17 +109,12 @@ struct uprobe { - */ - static bool valid_vma(struct vm_area_struct *vma, bool is_register) - { -- if (!vma->vm_file) -- return false; -+ vm_flags_t flags = VM_HUGETLB | VM_MAYEXEC | VM_SHARED; - -- if (!is_register) -- return true; -+ if (is_register) -+ flags |= VM_WRITE; - -- if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) -- == (VM_READ|VM_EXEC)) -- return true; -- -- return false; -+ return vma->vm_file && (vma->vm_flags & flags) == VM_MAYEXEC; - } - - static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset) -@@ -188,19 +192,44 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn) - return *insn == UPROBE_SWBP_INSN; - } - -+static void copy_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *opcode) -+{ -+ void *kaddr = kmap_atomic(page); -+ memcpy(opcode, kaddr + (vaddr & ~PAGE_MASK), UPROBE_SWBP_INSN_SIZE); -+ kunmap_atomic(kaddr); -+} -+ -+static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *new_opcode) -+{ -+ uprobe_opcode_t old_opcode; -+ bool is_swbp; -+ -+ copy_opcode(page, vaddr, &old_opcode); -+ is_swbp = is_swbp_insn(&old_opcode); -+ -+ if (is_swbp_insn(new_opcode)) { -+ if (is_swbp) /* register: already installed? */ -+ return 0; -+ } else { -+ if (!is_swbp) /* unregister: was it changed by us? */ -+ return 0; -+ } -+ -+ return 1; -+} -+ - /* - * NOTE: - * Expect the breakpoint instruction to be the smallest size instruction for - * the architecture. If an arch has variable length instruction and the - * breakpoint instruction is not of the smallest length instruction -- * supported by that architecture then we need to modify read_opcode / -+ * supported by that architecture then we need to modify is_swbp_at_addr and - * write_opcode accordingly. This would never be a problem for archs that - * have fixed length instructions. - */ - - /* - * write_opcode - write the opcode at a given virtual address. -- * @auprobe: arch breakpointing information. - * @mm: the probed process address space. - * @vaddr: the virtual address to store the opcode. - * @opcode: opcode to be written at @vaddr. -@@ -211,8 +240,8 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn) - * For mm @mm, write the opcode at @vaddr. - * Return 0 (success) or a negative errno. - */ --static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, -- unsigned long vaddr, uprobe_opcode_t opcode) -+static int write_opcode(struct mm_struct *mm, unsigned long vaddr, -+ uprobe_opcode_t opcode) - { - struct page *old_page, *new_page; - void *vaddr_old, *vaddr_new; -@@ -221,10 +250,14 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, - - retry: - /* Read the page with vaddr into memory */ -- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma); -+ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma); - if (ret <= 0) - return ret; - -+ ret = verify_opcode(old_page, vaddr, &opcode); -+ if (ret <= 0) -+ goto put_old; -+ - ret = -ENOMEM; - new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr); - if (!new_page) -@@ -259,65 +292,6 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, - } - - /** -- * read_opcode - read the opcode at a given virtual address. -- * @mm: the probed process address space. -- * @vaddr: the virtual address to read the opcode. -- * @opcode: location to store the read opcode. -- * -- * Called with mm->mmap_sem held (for read and with a reference to -- * mm. -- * -- * For mm @mm, read the opcode at @vaddr and store it in @opcode. -- * Return 0 (success) or a negative errno. -- */ --static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t *opcode) --{ -- struct page *page; -- void *vaddr_new; -- int ret; -- -- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL); -- if (ret <= 0) -- return ret; -- -- lock_page(page); -- vaddr_new = kmap_atomic(page); -- vaddr &= ~PAGE_MASK; -- memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE); -- kunmap_atomic(vaddr_new); -- unlock_page(page); -- -- put_page(page); -- -- return 0; --} -- --static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) --{ -- uprobe_opcode_t opcode; -- int result; -- -- if (current->mm == mm) { -- pagefault_disable(); -- result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr, -- sizeof(opcode)); -- pagefault_enable(); -- -- if (likely(result == 0)) -- goto out; -- } -- -- result = read_opcode(mm, vaddr, &opcode); -- if (result) -- return result; --out: -- if (is_swbp_insn(&opcode)) -- return 1; -- -- return 0; --} -- --/** - * set_swbp - store breakpoint at a given address. - * @auprobe: arch specific probepoint information. - * @mm: the probed process address space. -@@ -328,18 +302,7 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) - */ - int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) - { -- int result; -- /* -- * See the comment near uprobes_hash(). -- */ -- result = is_swbp_at_addr(mm, vaddr); -- if (result == 1) -- return -EEXIST; -- -- if (result) -- return result; -- -- return write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN); -+ return write_opcode(mm, vaddr, UPROBE_SWBP_INSN); - } - - /** -@@ -347,25 +310,14 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned - * @mm: the probed process address space. - * @auprobe: arch specific probepoint information. - * @vaddr: the virtual address to insert the opcode. -- * @verify: if true, verify existance of breakpoint instruction. - * - * For mm @mm, restore the original opcode (opcode) at @vaddr. - * Return 0 (success) or a negative errno. - */ - int __weak --set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, bool verify) -+set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) - { -- if (verify) { -- int result; -- -- result = is_swbp_at_addr(mm, vaddr); -- if (!result) -- return -EINVAL; -- -- if (result != 1) -- return result; -- } -- return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); -+ return write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); - } - - static int match_uprobe(struct uprobe *l, struct uprobe *r) -@@ -415,11 +367,10 @@ static struct uprobe *__find_uprobe(struct inode *inode, loff_t offset) - static struct uprobe *find_uprobe(struct inode *inode, loff_t offset) - { - struct uprobe *uprobe; -- unsigned long flags; - -- spin_lock_irqsave(&uprobes_treelock, flags); -+ spin_lock(&uprobes_treelock); - uprobe = __find_uprobe(inode, offset); -- spin_unlock_irqrestore(&uprobes_treelock, flags); -+ spin_unlock(&uprobes_treelock); - - return uprobe; - } -@@ -466,15 +417,14 @@ static struct uprobe *__insert_uprobe(struct uprobe *uprobe) - */ - static struct uprobe *insert_uprobe(struct uprobe *uprobe) - { -- unsigned long flags; - struct uprobe *u; - -- spin_lock_irqsave(&uprobes_treelock, flags); -+ spin_lock(&uprobes_treelock); - u = __insert_uprobe(uprobe); -- spin_unlock_irqrestore(&uprobes_treelock, flags); -+ spin_unlock(&uprobes_treelock); - - /* For now assume that the instruction need not be single-stepped */ -- uprobe->flags |= UPROBE_SKIP_SSTEP; -+ __set_bit(UPROBE_SKIP_SSTEP, &uprobe->flags); - - return u; - } -@@ -496,6 +446,7 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) - uprobe->inode = igrab(inode); - uprobe->offset = offset; - init_rwsem(&uprobe->consumer_rwsem); -+ mutex_init(&uprobe->copy_mutex); - - /* add to uprobes_tree, sorted on inode:offset */ - cur_uprobe = insert_uprobe(uprobe); -@@ -516,7 +467,7 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) - { - struct uprobe_consumer *uc; - -- if (!(uprobe->flags & UPROBE_RUN_HANDLER)) -+ if (!test_bit(UPROBE_RUN_HANDLER, &uprobe->flags)) - return; - - down_read(&uprobe->consumer_rwsem); -@@ -622,33 +573,48 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp) - return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset); - } - --/* -- * How mm->uprobes_state.count gets updated -- * uprobe_mmap() increments the count if -- * - it successfully adds a breakpoint. -- * - it cannot add a breakpoint, but sees that there is a underlying -- * breakpoint (via a is_swbp_at_addr()). -- * -- * uprobe_munmap() decrements the count if -- * - it sees a underlying breakpoint, (via is_swbp_at_addr) -- * (Subsequent uprobe_unregister wouldnt find the breakpoint -- * unless a uprobe_mmap kicks in, since the old vma would be -- * dropped just after uprobe_munmap.) -- * -- * uprobe_register increments the count if: -- * - it successfully adds a breakpoint. -- * -- * uprobe_unregister decrements the count if: -- * - it sees a underlying breakpoint and removes successfully. -- * (via is_swbp_at_addr) -- * (Subsequent uprobe_munmap wouldnt find the breakpoint -- * since there is no underlying breakpoint after the -- * breakpoint removal.) -- */ -+static int prepare_uprobe(struct uprobe *uprobe, struct file *file, -+ struct mm_struct *mm, unsigned long vaddr) -+{ -+ int ret = 0; -+ -+ if (test_bit(UPROBE_COPY_INSN, &uprobe->flags)) -+ return ret; -+ -+ mutex_lock(&uprobe->copy_mutex); -+ if (test_bit(UPROBE_COPY_INSN, &uprobe->flags)) -+ goto out; -+ -+ ret = copy_insn(uprobe, file); -+ if (ret) -+ goto out; -+ -+ ret = -ENOTSUPP; -+ if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) -+ goto out; -+ -+ ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); -+ if (ret) -+ goto out; -+ -+ /* write_opcode() assumes we don't cross page boundary */ -+ BUG_ON((uprobe->offset & ~PAGE_MASK) + -+ UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); -+ -+ smp_wmb(); /* pairs with rmb() in find_active_uprobe() */ -+ set_bit(UPROBE_COPY_INSN, &uprobe->flags); -+ -+ out: -+ mutex_unlock(&uprobe->copy_mutex); -+ -+ return ret; -+} -+ - static int - install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, - struct vm_area_struct *vma, unsigned long vaddr) - { -+ bool first_uprobe; - int ret; - - /* -@@ -659,48 +625,38 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, - * Hence behave as if probe already existed. - */ - if (!uprobe->consumers) -- return -EEXIST; -- -- if (!(uprobe->flags & UPROBE_COPY_INSN)) { -- ret = copy_insn(uprobe, vma->vm_file); -- if (ret) -- return ret; -- -- if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) -- return -ENOTSUPP; -- -- ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); -- if (ret) -- return ret; -- -- /* write_opcode() assumes we don't cross page boundary */ -- BUG_ON((uprobe->offset & ~PAGE_MASK) + -- UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); -+ return 0; - -- uprobe->flags |= UPROBE_COPY_INSN; -- } -+ ret = prepare_uprobe(uprobe, vma->vm_file, mm, vaddr); -+ if (ret) -+ return ret; - - /* -- * Ideally, should be updating the probe count after the breakpoint -- * has been successfully inserted. However a thread could hit the -- * breakpoint we just inserted even before the probe count is -- * incremented. If this is the first breakpoint placed, breakpoint -- * notifier might ignore uprobes and pass the trap to the thread. -- * Hence increment before and decrement on failure. -+ * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(), -+ * the task can hit this breakpoint right after __replace_page(). - */ -- atomic_inc(&mm->uprobes_state.count); -+ first_uprobe = !test_bit(MMF_HAS_UPROBES, &mm->flags); -+ if (first_uprobe) -+ set_bit(MMF_HAS_UPROBES, &mm->flags); -+ - ret = set_swbp(&uprobe->arch, mm, vaddr); -- if (ret) -- atomic_dec(&mm->uprobes_state.count); -+ if (!ret) -+ clear_bit(MMF_RECALC_UPROBES, &mm->flags); -+ else if (first_uprobe) -+ clear_bit(MMF_HAS_UPROBES, &mm->flags); - - return ret; - } - --static void -+static int - remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr) - { -- if (!set_orig_insn(&uprobe->arch, mm, vaddr, true)) -- atomic_dec(&mm->uprobes_state.count); -+ /* can happen if uprobe_register() fails */ -+ if (!test_bit(MMF_HAS_UPROBES, &mm->flags)) -+ return 0; -+ -+ set_bit(MMF_RECALC_UPROBES, &mm->flags); -+ return set_orig_insn(&uprobe->arch, mm, vaddr); - } - - /* -@@ -710,11 +666,9 @@ remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vad - */ - static void delete_uprobe(struct uprobe *uprobe) - { -- unsigned long flags; -- -- spin_lock_irqsave(&uprobes_treelock, flags); -+ spin_lock(&uprobes_treelock); - rb_erase(&uprobe->rb_node, &uprobes_tree); -- spin_unlock_irqrestore(&uprobes_treelock, flags); -+ spin_unlock(&uprobes_treelock); - iput(uprobe->inode); - put_uprobe(uprobe); - atomic_dec(&uprobe_events); -@@ -818,7 +772,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register) - struct mm_struct *mm = info->mm; - struct vm_area_struct *vma; - -- if (err) -+ if (err && is_register) - goto free; - - down_write(&mm->mmap_sem); -@@ -831,17 +785,11 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register) - vaddr_to_offset(vma, info->vaddr) != uprobe->offset) - goto unlock; - -- if (is_register) { -+ if (is_register) - err = install_breakpoint(uprobe, mm, vma, info->vaddr); -- /* -- * We can race against uprobe_mmap(), see the -- * comment near uprobe_hash(). -- */ -- if (err == -EEXIST) -- err = 0; -- } else { -- remove_breakpoint(uprobe, mm, info->vaddr); -- } -+ else -+ err |= remove_breakpoint(uprobe, mm, info->vaddr); -+ - unlock: - up_write(&mm->mmap_sem); - free: -@@ -897,21 +845,25 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer * - mutex_lock(uprobes_hash(inode)); - uprobe = alloc_uprobe(inode, offset); - -- if (uprobe && !consumer_add(uprobe, uc)) { -+ if (!uprobe) { -+ ret = -ENOMEM; -+ } else if (!consumer_add(uprobe, uc)) { - ret = __uprobe_register(uprobe); - if (ret) { - uprobe->consumers = NULL; - __uprobe_unregister(uprobe); - } else { -- uprobe->flags |= UPROBE_RUN_HANDLER; -+ set_bit(UPROBE_RUN_HANDLER, &uprobe->flags); - } - } - - mutex_unlock(uprobes_hash(inode)); -- put_uprobe(uprobe); -+ if (uprobe) -+ put_uprobe(uprobe); - - return ret; - } -+EXPORT_SYMBOL_GPL(uprobe_register); - - /* - * uprobe_unregister - unregister a already registered probe. -@@ -935,7 +887,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume - if (consumer_del(uprobe, uc)) { - if (!uprobe->consumers) { - __uprobe_unregister(uprobe); -- uprobe->flags &= ~UPROBE_RUN_HANDLER; -+ clear_bit(UPROBE_RUN_HANDLER, &uprobe->flags); - } - } - -@@ -943,6 +895,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume - if (uprobe) - put_uprobe(uprobe); - } -+EXPORT_SYMBOL_GPL(uprobe_unregister); - - static struct rb_node * - find_node_in_range(struct inode *inode, loff_t min, loff_t max) -@@ -978,7 +931,6 @@ static void build_probe_list(struct inode *inode, - struct list_head *head) - { - loff_t min, max; -- unsigned long flags; - struct rb_node *n, *t; - struct uprobe *u; - -@@ -986,7 +938,7 @@ static void build_probe_list(struct inode *inode, - min = vaddr_to_offset(vma, start); - max = min + (end - start) - 1; - -- spin_lock_irqsave(&uprobes_treelock, flags); -+ spin_lock(&uprobes_treelock); - n = find_node_in_range(inode, min, max); - if (n) { - for (t = n; t; t = rb_prev(t)) { -@@ -1004,27 +956,20 @@ static void build_probe_list(struct inode *inode, - atomic_inc(&u->ref); - } - } -- spin_unlock_irqrestore(&uprobes_treelock, flags); -+ spin_unlock(&uprobes_treelock); - } - - /* -- * Called from mmap_region. -- * called with mm->mmap_sem acquired. -- * -- * Return -ve no if we fail to insert probes and we cannot -- * bail-out. -- * Return 0 otherwise. i.e: -+ * Called from mmap_region/vma_adjust with mm->mmap_sem acquired. - * -- * - successful insertion of probes -- * - (or) no possible probes to be inserted. -- * - (or) insertion of probes failed but we can bail-out. -+ * Currently we ignore all errors and always return 0, the callers -+ * can't handle the failure anyway. - */ - int uprobe_mmap(struct vm_area_struct *vma) - { - struct list_head tmp_list; - struct uprobe *uprobe, *u; - struct inode *inode; -- int ret, count; - - if (!atomic_read(&uprobe_events) || !valid_vma(vma, true)) - return 0; -@@ -1036,44 +981,35 @@ int uprobe_mmap(struct vm_area_struct *vma) - mutex_lock(uprobes_mmap_hash(inode)); - build_probe_list(inode, vma, vma->vm_start, vma->vm_end, &tmp_list); - -- ret = 0; -- count = 0; -- - list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { -- if (!ret) { -+ if (!fatal_signal_pending(current)) { - unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset); -- -- ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); -- /* -- * We can race against uprobe_register(), see the -- * comment near uprobe_hash(). -- */ -- if (ret == -EEXIST) { -- ret = 0; -- -- if (!is_swbp_at_addr(vma->vm_mm, vaddr)) -- continue; -- -- /* -- * Unable to insert a breakpoint, but -- * breakpoint lies underneath. Increment the -- * probe count. -- */ -- atomic_inc(&vma->vm_mm->uprobes_state.count); -- } -- -- if (!ret) -- count++; -+ install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); - } - put_uprobe(uprobe); - } -- - mutex_unlock(uprobes_mmap_hash(inode)); - -- if (ret) -- atomic_sub(count, &vma->vm_mm->uprobes_state.count); -+ return 0; -+} - -- return ret; -+static bool -+vma_has_uprobes(struct vm_area_struct *vma, unsigned long start, unsigned long end) -+{ -+ loff_t min, max; -+ struct inode *inode; -+ struct rb_node *n; -+ -+ inode = vma->vm_file->f_mapping->host; -+ -+ min = vaddr_to_offset(vma, start); -+ max = min + (end - start) - 1; -+ -+ spin_lock(&uprobes_treelock); -+ n = find_node_in_range(inode, min, max); -+ spin_unlock(&uprobes_treelock); -+ -+ return !!n; - } - - /* -@@ -1081,37 +1017,18 @@ int uprobe_mmap(struct vm_area_struct *vma) - */ - void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) - { -- struct list_head tmp_list; -- struct uprobe *uprobe, *u; -- struct inode *inode; -- - if (!atomic_read(&uprobe_events) || !valid_vma(vma, false)) - return; - - if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */ - return; - -- if (!atomic_read(&vma->vm_mm->uprobes_state.count)) -- return; -- -- inode = vma->vm_file->f_mapping->host; -- if (!inode) -+ if (!test_bit(MMF_HAS_UPROBES, &vma->vm_mm->flags) || -+ test_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags)) - return; - -- mutex_lock(uprobes_mmap_hash(inode)); -- build_probe_list(inode, vma, start, end, &tmp_list); -- -- list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { -- unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset); -- /* -- * An unregister could have removed the probe before -- * unmap. So check before we decrement the count. -- */ -- if (is_swbp_at_addr(vma->vm_mm, vaddr) == 1) -- atomic_dec(&vma->vm_mm->uprobes_state.count); -- put_uprobe(uprobe); -- } -- mutex_unlock(uprobes_mmap_hash(inode)); -+ if (vma_has_uprobes(vma, start, end)) -+ set_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags); - } - - /* Slot allocation for XOL */ -@@ -1213,13 +1130,15 @@ void uprobe_clear_state(struct mm_struct *mm) - kfree(area); - } - --/* -- * uprobe_reset_state - Free the area allocated for slots. -- */ --void uprobe_reset_state(struct mm_struct *mm) -+void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) - { -- mm->uprobes_state.xol_area = NULL; -- atomic_set(&mm->uprobes_state.count, 0); -+ newmm->uprobes_state.xol_area = NULL; -+ -+ if (test_bit(MMF_HAS_UPROBES, &oldmm->flags)) { -+ set_bit(MMF_HAS_UPROBES, &newmm->flags); -+ /* unconditionally, dup_mmap() skips VM_DONTCOPY vmas */ -+ set_bit(MMF_RECALC_UPROBES, &newmm->flags); -+ } - } - - /* -@@ -1430,13 +1349,57 @@ bool uprobe_deny_signal(void) - */ - static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs) - { -- if (arch_uprobe_skip_sstep(&uprobe->arch, regs)) -- return true; -- -- uprobe->flags &= ~UPROBE_SKIP_SSTEP; -+ if (test_bit(UPROBE_SKIP_SSTEP, &uprobe->flags)) { -+ if (arch_uprobe_skip_sstep(&uprobe->arch, regs)) -+ return true; -+ clear_bit(UPROBE_SKIP_SSTEP, &uprobe->flags); -+ } - return false; - } - -+static void mmf_recalc_uprobes(struct mm_struct *mm) -+{ -+ struct vm_area_struct *vma; -+ -+ for (vma = mm->mmap; vma; vma = vma->vm_next) { -+ if (!valid_vma(vma, false)) -+ continue; -+ /* -+ * This is not strictly accurate, we can race with -+ * uprobe_unregister() and see the already removed -+ * uprobe if delete_uprobe() was not yet called. -+ */ -+ if (vma_has_uprobes(vma, vma->vm_start, vma->vm_end)) -+ return; -+ } -+ -+ clear_bit(MMF_HAS_UPROBES, &mm->flags); -+} -+ -+static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) -+{ -+ struct page *page; -+ uprobe_opcode_t opcode; -+ int result; -+ -+ pagefault_disable(); -+ result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr, -+ sizeof(opcode)); -+ pagefault_enable(); -+ -+ if (likely(result == 0)) -+ goto out; -+ -+ result = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL); -+ if (result < 0) -+ return result; -+ -+ copy_opcode(page, vaddr, &opcode); -+ put_page(page); -+ out: -+ return is_swbp_insn(&opcode); -+} -+ - static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) - { - struct mm_struct *mm = current->mm; -@@ -1458,11 +1421,24 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) - } else { - *is_swbp = -EFAULT; - } -+ -+ if (!uprobe && test_and_clear_bit(MMF_RECALC_UPROBES, &mm->flags)) -+ mmf_recalc_uprobes(mm); - up_read(&mm->mmap_sem); - - return uprobe; - } - -+void __weak arch_uprobe_enable_step(struct arch_uprobe *arch) -+{ -+ user_enable_single_step(current); -+} -+ -+void __weak arch_uprobe_disable_step(struct arch_uprobe *arch) -+{ -+ user_disable_single_step(current); -+} -+ - /* - * Run handler and ask thread to singlestep. - * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. -@@ -1494,41 +1470,42 @@ static void handle_swbp(struct pt_regs *regs) - } - return; - } -+ /* -+ * TODO: move copy_insn/etc into _register and remove this hack. -+ * After we hit the bp, _unregister + _register can install the -+ * new and not-yet-analyzed uprobe at the same address, restart. -+ */ -+ smp_rmb(); /* pairs with wmb() in install_breakpoint() */ -+ if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags))) -+ goto restart; - - utask = current->utask; - if (!utask) { - utask = add_utask(); - /* Cannot allocate; re-execute the instruction. */ - if (!utask) -- goto cleanup_ret; -+ goto restart; - } -- utask->active_uprobe = uprobe; -+ - handler_chain(uprobe, regs); -- if (uprobe->flags & UPROBE_SKIP_SSTEP && can_skip_sstep(uprobe, regs)) -- goto cleanup_ret; -+ if (can_skip_sstep(uprobe, regs)) -+ goto out; - -- utask->state = UTASK_SSTEP; - if (!pre_ssout(uprobe, regs, bp_vaddr)) { -- user_enable_single_step(current); -+ arch_uprobe_enable_step(&uprobe->arch); -+ utask->active_uprobe = uprobe; -+ utask->state = UTASK_SSTEP; - return; - } - --cleanup_ret: -- if (utask) { -- utask->active_uprobe = NULL; -- utask->state = UTASK_RUNNING; -- } -- if (uprobe) { -- if (!(uprobe->flags & UPROBE_SKIP_SSTEP)) -- -- /* -- * cannot singlestep; cannot skip instruction; -- * re-execute the instruction. -- */ -- instruction_pointer_set(regs, bp_vaddr); -- -- put_uprobe(uprobe); -- } -+restart: -+ /* -+ * cannot singlestep; cannot skip instruction; -+ * re-execute the instruction. -+ */ -+ instruction_pointer_set(regs, bp_vaddr); -+out: -+ put_uprobe(uprobe); - } - - /* -@@ -1547,10 +1524,10 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) - else - WARN_ON_ONCE(1); - -+ arch_uprobe_disable_step(&uprobe->arch); - put_uprobe(uprobe); - utask->active_uprobe = NULL; - utask->state = UTASK_RUNNING; -- user_disable_single_step(current); - xol_free_insn_slot(current); - - spin_lock_irq(¤t->sighand->siglock); -@@ -1559,13 +1536,12 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) - } - - /* -- * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag. (and on -- * subsequent probe hits on the thread sets the state to UTASK_BP_HIT) and -- * allows the thread to return from interrupt. -+ * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag and -+ * allows the thread to return from interrupt. After that handle_swbp() -+ * sets utask->active_uprobe. - * -- * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag and -- * also sets the state to UTASK_SSTEP_ACK and allows the thread to return from -- * interrupt. -+ * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag -+ * and allows the thread to return from interrupt. - * - * While returning to userspace, thread notices the TIF_UPROBE flag and calls - * uprobe_notify_resume(). -@@ -1574,11 +1550,13 @@ void uprobe_notify_resume(struct pt_regs *regs) - { - struct uprobe_task *utask; - -+ clear_thread_flag(TIF_UPROBE); -+ - utask = current->utask; -- if (!utask || utask->state == UTASK_BP_HIT) -- handle_swbp(regs); -- else -+ if (utask && utask->active_uprobe) - handle_singlestep(utask, regs); -+ else -+ handle_swbp(regs); - } - - /* -@@ -1587,18 +1565,10 @@ void uprobe_notify_resume(struct pt_regs *regs) - */ - int uprobe_pre_sstep_notifier(struct pt_regs *regs) - { -- struct uprobe_task *utask; -- -- if (!current->mm || !atomic_read(¤t->mm->uprobes_state.count)) -- /* task is currently not uprobed */ -+ if (!current->mm || !test_bit(MMF_HAS_UPROBES, ¤t->mm->flags)) - return 0; - -- utask = current->utask; -- if (utask) -- utask->state = UTASK_BP_HIT; -- - set_thread_flag(TIF_UPROBE); -- - return 1; - } - -diff --git a/kernel/fork.c b/kernel/fork.c -index 2c8857e..2343c9e 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -353,6 +353,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) - - down_write(&oldmm->mmap_sem); - flush_cache_dup_mm(oldmm); -+ uprobe_dup_mmap(oldmm, mm); - /* - * Not linked in yet - no deadlock potential: - */ -@@ -454,9 +455,6 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) - - if (retval) - goto out; -- -- if (file) -- uprobe_mmap(tmp); - } - /* a new mm has just been created */ - arch_dup_mmap(oldmm, mm); -@@ -839,8 +837,6 @@ struct mm_struct *dup_mm(struct task_struct *tsk) - #ifdef CONFIG_TRANSPARENT_HUGEPAGE - mm->pmd_huge_pte = NULL; - #endif -- uprobe_reset_state(mm); -- - if (!mm_init(mm, tsk)) - goto fail_nomem; - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index a232bb5..764fcd1 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -33,6 +33,12 @@ static int ptrace_trapping_sleep_fn(void *flags) - } - - /* -+ * This is declared in linux/regset.h and defined in machine-dependent -+ * code. We put the export here to ensure no machine forgets it. -+ */ -+EXPORT_SYMBOL_GPL(task_user_regset_view); -+ -+/* - * ptrace a task: make the debugger its new parent and - * move it to the ptrace list. - * -_______________________________________________ -kernel mailing list -kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel diff --git a/freed-ora/current/f18/vt-Drop-K_OFF-for-VC_MUTE.patch b/freed-ora/current/f18/vt-Drop-K_OFF-for-VC_MUTE.patch index ab85411cb..e9bc4fffa 100644 --- a/freed-ora/current/f18/vt-Drop-K_OFF-for-VC_MUTE.patch +++ b/freed-ora/current/f18/vt-Drop-K_OFF-for-VC_MUTE.patch @@ -64,7 +64,7 @@ Signed-off-by: Adam Jackson <ajax@redhat.com> drivers/tty/vt/vt_ioctl.c | 13 +++++++++++++ include/linux/kbd_kern.h | 6 +++--- include/linux/vt_kern.h | 2 ++ - include/linux/kd.h | 5 +++++ + include/uapi/linux/kd.h | 5 +++++ 5 files changed, 56 insertions(+), 10 deletions(-) diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c @@ -222,10 +222,10 @@ index 50ae7d0..a886915 100644 extern int vt_do_kdgkbmode(int console); extern int vt_do_kdgkbmeta(int console); extern void vt_reset_unicode(int console); -diff --git a/include/linux/kd.h b/include/linux/kd.h +diff --git a/include/uapi/linux/kd.h b/include/uapi/linux/kd.h index 87b7cc4..c3de63c 100644 ---- a/include/linux/kd.h -+++ b/include/linux/kd.h +--- a/include/uapi/linux/kd.h ++++ b/include/uapi/linux/kd.h @@ -81,6 +81,7 @@ struct unimapinit { #define K_XLATE 0x01 #define K_MEDIUMRAW 0x02 |