From 111d639dd659bc1496a63cb8854abab8a15f3728 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:45:23 -0800 Subject: fs/befs/linuxvfs.c: remove unnecessary casting Fix the following coccinelle warning: fs/befs/linuxvfs.c:278:14-36: WARNING: casting value returned by memory allocation function to (struct befs_inode_info *) is useless. [akpm@linux-foundation.org: avoid 80-col ugliness] Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index edf4777..e089f19 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -274,9 +274,9 @@ more: static struct inode * befs_alloc_inode(struct super_block *sb) { - struct befs_inode_info *bi; - bi = (struct befs_inode_info *)kmem_cache_alloc(befs_inode_cachep, - GFP_KERNEL); + struct befs_inode_info *bi; + + bi = kmem_cache_alloc(befs_inode_cachep, GFP_KERNEL); if (!bi) return NULL; return &bi->vfs_inode; -- cgit v0.10.2 From b625032b10222c4406979c7604189f2bef29c5d0 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:45:25 -0800 Subject: fs/coda/dir.c: forward declaration clean-up - Move operation structures to avoid forward declarations. - Fix some checkpatch warnings: WARNING: Missing a blank line after declarations + struct inode *host_inode = file_inode(host_file); + mutex_lock(&host_inode->i_mutex); ERROR: that open brace { should be on the previous line +const struct dentry_operations coda_dentry_operations = +{ ERROR: that open brace { should be on the previous line +const struct inode_operations coda_dir_inode_operations = +{ Signed-off-by: Fabian Frederick Cc: Jan Harkes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 86c8938..281ee01 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -28,29 +28,6 @@ #include "coda_int.h" -/* dir inode-ops */ -static int coda_create(struct inode *dir, struct dentry *new, umode_t mode, bool excl); -static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, unsigned int flags); -static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, - struct dentry *entry); -static int coda_unlink(struct inode *dir_inode, struct dentry *entry); -static int coda_symlink(struct inode *dir_inode, struct dentry *entry, - const char *symname); -static int coda_mkdir(struct inode *dir_inode, struct dentry *entry, umode_t mode); -static int coda_rmdir(struct inode *dir_inode, struct dentry *entry); -static int coda_rename(struct inode *old_inode, struct dentry *old_dentry, - struct inode *new_inode, struct dentry *new_dentry); - -/* dir file-ops */ -static int coda_readdir(struct file *file, struct dir_context *ctx); - -/* dentry ops */ -static int coda_dentry_revalidate(struct dentry *de, unsigned int flags); -static int coda_dentry_delete(const struct dentry *); - -/* support routines */ -static int coda_venus_readdir(struct file *, struct dir_context *); - /* same as fs/bad_inode.c */ static int coda_return_EIO(void) { @@ -58,38 +35,6 @@ static int coda_return_EIO(void) } #define CODA_EIO_ERROR ((void *) (coda_return_EIO)) -const struct dentry_operations coda_dentry_operations = -{ - .d_revalidate = coda_dentry_revalidate, - .d_delete = coda_dentry_delete, -}; - -const struct inode_operations coda_dir_inode_operations = -{ - .create = coda_create, - .lookup = coda_lookup, - .link = coda_link, - .unlink = coda_unlink, - .symlink = coda_symlink, - .mkdir = coda_mkdir, - .rmdir = coda_rmdir, - .mknod = CODA_EIO_ERROR, - .rename = coda_rename, - .permission = coda_permission, - .getattr = coda_getattr, - .setattr = coda_setattr, -}; - -const struct file_operations coda_dir_operations = { - .llseek = generic_file_llseek, - .read = generic_read_dir, - .iterate = coda_readdir, - .open = coda_open, - .release = coda_release, - .fsync = coda_fsync, -}; - - /* inode operations for directories */ /* access routines: lookup, readlink, permission */ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, unsigned int flags) @@ -374,33 +319,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, return error; } - -/* file operations for directories */ -static int coda_readdir(struct file *coda_file, struct dir_context *ctx) -{ - struct coda_file_info *cfi; - struct file *host_file; - int ret; - - cfi = CODA_FTOC(coda_file); - BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); - host_file = cfi->cfi_container; - - if (host_file->f_op->iterate) { - struct inode *host_inode = file_inode(host_file); - mutex_lock(&host_inode->i_mutex); - ret = -ENOENT; - if (!IS_DEADDIR(host_inode)) { - ret = host_file->f_op->iterate(host_file, ctx); - file_accessed(host_file); - } - mutex_unlock(&host_inode->i_mutex); - return ret; - } - /* Venus: we must read Venus dirents from a file */ - return coda_venus_readdir(coda_file, ctx); -} - static inline unsigned int CDT2DT(unsigned char cdt) { unsigned int dt; @@ -495,6 +413,33 @@ out: return 0; } +/* file operations for directories */ +static int coda_readdir(struct file *coda_file, struct dir_context *ctx) +{ + struct coda_file_info *cfi; + struct file *host_file; + int ret; + + cfi = CODA_FTOC(coda_file); + BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); + host_file = cfi->cfi_container; + + if (host_file->f_op->iterate) { + struct inode *host_inode = file_inode(host_file); + + mutex_lock(&host_inode->i_mutex); + ret = -ENOENT; + if (!IS_DEADDIR(host_inode)) { + ret = host_file->f_op->iterate(host_file, ctx); + file_accessed(host_file); + } + mutex_unlock(&host_inode->i_mutex); + return ret; + } + /* Venus: we must read Venus dirents from a file */ + return coda_venus_readdir(coda_file, ctx); +} + /* called when a cache lookup succeeds */ static int coda_dentry_revalidate(struct dentry *de, unsigned int flags) { @@ -603,3 +548,32 @@ int coda_revalidate_inode(struct inode *inode) } return 0; } + +const struct dentry_operations coda_dentry_operations = { + .d_revalidate = coda_dentry_revalidate, + .d_delete = coda_dentry_delete, +}; + +const struct inode_operations coda_dir_inode_operations = { + .create = coda_create, + .lookup = coda_lookup, + .link = coda_link, + .unlink = coda_unlink, + .symlink = coda_symlink, + .mkdir = coda_mkdir, + .rmdir = coda_rmdir, + .mknod = CODA_EIO_ERROR, + .rename = coda_rename, + .permission = coda_permission, + .getattr = coda_getattr, + .setattr = coda_setattr, +}; + +const struct file_operations coda_dir_operations = { + .llseek = generic_file_llseek, + .read = generic_read_dir, + .iterate = coda_readdir, + .open = coda_open, + .release = coda_release, + .fsync = coda_fsync, +}; -- cgit v0.10.2 From 61da3ae241f4382e30beb6de06c4dacada37f520 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:45:28 -0800 Subject: fs/ufs/super.c: remove unnecessary casting Fix the following coccinelle warning: fs/ufs/super.c:1418:7-28: WARNING: casting value returned by memory allocation function to (struct ufs_inode_info *) is useless. Signed-off-by: Fabian Frederick Cc: Evgeniy Dushistov Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ufs/super.c b/fs/ufs/super.c index da73801..e515e99 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1415,9 +1415,11 @@ static struct kmem_cache * ufs_inode_cachep; static struct inode *ufs_alloc_inode(struct super_block *sb) { struct ufs_inode_info *ei; - ei = (struct ufs_inode_info *)kmem_cache_alloc(ufs_inode_cachep, GFP_NOFS); + + ei = kmem_cache_alloc(ufs_inode_cachep, GFP_NOFS); if (!ei) return NULL; + ei->vfs_inode.i_version = 1; return &ei->vfs_inode; } -- cgit v0.10.2 From ed3ad79f87f31beed64778af0b29aff3074f700e Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:45:31 -0800 Subject: fs/ufs/super.c: fix potential race condition Let locking subsystem decide on mutex management. As reported by Andrew Morton this patch fixes a bug: : lock_ufs() is assuming that on non-preempt uniprocessor, the calling : code will run atomically up to the matching unlock_ufs(). : : But that isn't true. The very first site I looked at (ufs_frag_map) : does sb_bread() under lock_ufs(). And sb_bread() will call schedule(), : very commonly. : : The ->mutex_owner stuff is a bit hacky but should work OK. Signed-off-by: Fabian Frederick Cc: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ufs/super.c b/fs/ufs/super.c index e515e99..8092d37 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -95,22 +95,18 @@ void lock_ufs(struct super_block *sb) { -#if defined(CONFIG_SMP) || defined (CONFIG_PREEMPT) struct ufs_sb_info *sbi = UFS_SB(sb); mutex_lock(&sbi->mutex); sbi->mutex_owner = current; -#endif } void unlock_ufs(struct super_block *sb) { -#if defined(CONFIG_SMP) || defined (CONFIG_PREEMPT) struct ufs_sb_info *sbi = UFS_SB(sb); sbi->mutex_owner = NULL; mutex_unlock(&sbi->mutex); -#endif } static struct inode *ufs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) -- cgit v0.10.2 From 714b71a3a91f63e0852ad9a07edc3820800c681f Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:45:33 -0800 Subject: fs/reiserfs/inode.c: replace 0 by NULL for pointers Fix sparse warning: fs/reiserfs/inode.c:2769:19: warning: Using plain integer as NULL pointer Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index a7eec98..e72401e 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -2766,7 +2766,7 @@ static int reiserfs_write_begin(struct file *file, int old_ref = 0; inode = mapping->host; - *fsdata = 0; + *fsdata = NULL; if (flags & AOP_FLAG_CONT_EXPAND && (pos & (inode->i_sb->s_blocksize - 1)) == 0) { pos ++; -- cgit v0.10.2 From d6bd428275f3f470fc7cf6624b737c6d7805b44b Mon Sep 17 00:00:00 2001 From: Fred Chou Date: Tue, 17 Feb 2015 13:45:36 -0800 Subject: fs: fat: use MSDOS_SB macro to get msdos_sb_info Use the MSDOS_SB macro to get msdos_sb_info, instead of coding it directly. Signed-off-by: Fred Chou Acked-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 7b41a2d..497c7c5 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -580,7 +580,7 @@ static void fat_set_state(struct super_block *sb, { struct buffer_head *bh; struct fat_boot_sector *b; - struct msdos_sb_info *sbi = sb->s_fs_info; + struct msdos_sb_info *sbi = MSDOS_SB(sb); /* do not change any thing if mounted read only */ if ((sb->s_flags & MS_RDONLY) && !force) -- cgit v0.10.2 From 1cca3385e6d556cd90cdc148c2f26af807fa3600 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:45:39 -0800 Subject: ptrace: remove linux/compat.h inclusion under CONFIG_COMPAT Commit 84c751bd4aeb ("ptrace: add ability to retrieve signals without removing from a queue (v4)") includes globally in ptrace.c This patch removes inclusion under if defined CONFIG_COMPAT. Signed-off-by: Fabian Frederick Acked-by: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 1eb9d90..227fec3 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -1077,7 +1077,6 @@ int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr, } #if defined CONFIG_COMPAT -#include int compat_ptrace_request(struct task_struct *child, compat_long_t request, compat_ulong_t addr, compat_ulong_t data) -- cgit v0.10.2 From 1df0135588ed4e6048c1608ec046e9a38ea91e8e Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Tue, 17 Feb 2015 13:45:41 -0800 Subject: signal: use current->state helpers Call __set_current_state() instead of assigning the new state directly. These interfaces also aid CONFIG_DEBUG_ATOMIC_SLEEP environments, keeping track of who changed the state. Signed-off-by: Davidlohr Bueso Acked-by: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/signal.c b/kernel/signal.c index 33a5275..a390499 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -3550,7 +3550,7 @@ SYSCALL_DEFINE2(signal, int, sig, __sighandler_t, handler) SYSCALL_DEFINE0(pause) { while (!signal_pending(current)) { - current->state = TASK_INTERRUPTIBLE; + __set_current_state(TASK_INTERRUPTIBLE); schedule(); } return -ERESTARTNOHAND; @@ -3563,7 +3563,7 @@ int sigsuspend(sigset_t *set) current->saved_sigmask = current->blocked; set_current_blocked(set); - current->state = TASK_INTERRUPTIBLE; + __set_current_state(TASK_INTERRUPTIBLE); schedule(); set_restore_sigmask(); return -ERESTARTNOHAND; -- cgit v0.10.2 From 73d7e3eac01da3cef32ab25cbc6a36a6202c4ea6 Mon Sep 17 00:00:00 2001 From: Baoquan He Date: Tue, 17 Feb 2015 13:45:44 -0800 Subject: kexec: remove never used member destination in kimage struct kimage has a member destination which is used to store the real destination address of each page when load segment from user space buffer to kernel. But we never retrieve the value stored in kimage->destination, so this member variable in kimage and its assignment operation are redundent code. I guess for_each_kimage_entry just does the work that kimage->destination is expected to do. So in this patch just make a cleanup to remove it. Signed-off-by: Baoquan He Cc: "Eric W. Biederman" Cc: Vivek Goyal Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 9d957b7..10da8e2 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -122,8 +122,6 @@ struct kimage { kimage_entry_t *entry; kimage_entry_t *last_entry; - unsigned long destination; - unsigned long start; struct page *control_code_page; struct page *swap_page; diff --git a/kernel/kexec.c b/kernel/kexec.c index c852776..35dcac4 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -856,8 +856,6 @@ static int kimage_set_destination(struct kimage *image, destination &= PAGE_MASK; result = kimage_add_entry(image, destination | IND_DESTINATION); - if (result == 0) - image->destination = destination; return result; } @@ -869,8 +867,6 @@ static int kimage_add_page(struct kimage *image, unsigned long page) page &= PAGE_MASK; result = kimage_add_entry(image, page | IND_SOURCE); - if (result == 0) - image->destination += PAGE_SIZE; return result; } -- cgit v0.10.2 From ad69934987eb04c8c3f912b19db878f280e55c8f Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Tue, 17 Feb 2015 13:45:47 -0800 Subject: kexec: fix a typo in comment Signed-off-by: Alexander Kuleshov Acked-by: "Eric W. Biederman" Acked-by: Vivek Goyal Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/kexec.c b/kernel/kexec.c index 35dcac4..e9a6be4 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -444,7 +444,7 @@ arch_kexec_apply_relocations(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, } /* - * Free up memory used by kernel, initrd, and comand line. This is temporary + * Free up memory used by kernel, initrd, and command line. This is temporary * memory allocation which is not needed any more after these buffers have * been loaded into separate segments and have been copied elsewhere. */ -- cgit v0.10.2 From 9dc5c05f45ca8101025046cda7f8aca8835204f2 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Tue, 17 Feb 2015 13:45:50 -0800 Subject: kexec: Fix make headers_check Remove the unneded declaration for a kexec_load() routine. Fixes errors like these when running 'make headers_check': include/uapi/linux/kexec.h: userspace cannot reference function or variable defined in the kernel Paul said: : The kexec_load declaration isn't very useful for userspace, see the patch : I submitted in http://lkml.kernel.org/r/1389791824.17407.9.camel@x220 . : And After my attempt the export of that declaration has also been : discussed in : http://lkml.kernel.org/r/115373b6ac68ee7a305975896e1c4971e8e51d4c.1408731991.git.geoff@infradead.org : : In that last discussion no one has been able to point to an actual user of : it. So, as far as I can tell, no one actually uses it. Which makes : sense, because including this header by itself doesn't give one access to : a useful definition of kexec_load. So why bother with the declaration? Signed-off-by: Geoff Levand Acked-by: Paul Bolle Cc: H. Peter Anvin Cc: Vivek Goyal Cc: Arnd Bergmann Cc: Benjamin Herrenschmidt Cc: Maximilian Attems Cc: Michal Marek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/uapi/linux/kexec.h b/include/uapi/linux/kexec.h index 6925f5b..99048e5 100644 --- a/include/uapi/linux/kexec.h +++ b/include/uapi/linux/kexec.h @@ -55,12 +55,6 @@ struct kexec_segment { size_t memsz; }; -/* Load a new kernel image as described by the kexec_segment array - * consisting of passed number of segments at the entry-point address. - * The flags allow different useage types. - */ -extern int kexec_load(void *, size_t, struct kexec_segment *, - unsigned long int); #endif /* __KERNEL__ */ #endif /* _UAPILINUX_KEXEC_H */ -- cgit v0.10.2 From 518a0c716377e5f2c6d22957a5937ec5f328ead1 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Tue, 17 Feb 2015 13:45:53 -0800 Subject: kexec: simplify conditional Simplify the code around one of the conditionals in the kexec_load syscall routine. The original code was confusing with a redundant check on KEXEC_ON_CRASH and comments outside of the conditional block. This change switches the order of the conditional check, and cleans up the comments for the conditional. There is no functional change to the code. Signed-off-by: Geoff Levand Acked-by: Vivek Goyal Cc: Arnd Bergmann Cc: Benjamin Herrenschmidt Cc: H. Peter Anvin Cc: Maximilian Attems Cc: Michal Marek Cc: Paul Bolle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/kexec.c b/kernel/kexec.c index e9a6be4..38c25b1 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1284,19 +1284,22 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, if (nr_segments > 0) { unsigned long i; - /* Loading another kernel to reboot into */ - if ((flags & KEXEC_ON_CRASH) == 0) - result = kimage_alloc_init(&image, entry, nr_segments, - segments, flags); - /* Loading another kernel to switch to if this one crashes */ - else if (flags & KEXEC_ON_CRASH) { - /* Free any current crash dump kernel before + if (flags & KEXEC_ON_CRASH) { + /* + * Loading another kernel to switch to if this one + * crashes. Free any current crash dump kernel before * we corrupt it. */ + kimage_free(xchg(&kexec_crash_image, NULL)); result = kimage_alloc_init(&image, entry, nr_segments, segments, flags); crash_map_reserved_pages(); + } else { + /* Loading another kernel to reboot into. */ + + result = kimage_alloc_init(&image, entry, nr_segments, + segments, flags); } if (result) goto out; -- cgit v0.10.2 From cf2df6396ba78014289f322839a5cc785f09e1fd Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Tue, 17 Feb 2015 13:45:56 -0800 Subject: kexec: add bit definitions for kimage entry flags Define new kexec preprocessor macros IND_*_BIT that define the bit position of the kimage entry flags. Change the existing IND_* flag macros to be defined as bit shifts of the corresponding IND_*_BIT macros. Also wrap all C language code in kexec.h with #if !defined(__ASSEMBLY__) so assembly files can include kexec.h to get the IND_* and IND_*_BIT macros. Some CPU instruction sets have tests for bit position which are convenient in implementing routines that operate on the kimage entry list. The addition of these bit position macros in a common location will avoid duplicate definitions and the chance that changes to the IND_* flags will not be propagated to assembly files. Signed-off-by: Geoff Levand Acked-by: Vivek Goyal Cc: Arnd Bergmann Cc: Benjamin Herrenschmidt Cc: H. Peter Anvin Cc: Maximilian Attems Cc: Michal Marek Cc: Paul Bolle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 10da8e2..1fd980c 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -1,6 +1,18 @@ #ifndef LINUX_KEXEC_H #define LINUX_KEXEC_H +#define IND_DESTINATION_BIT 0 +#define IND_INDIRECTION_BIT 1 +#define IND_DONE_BIT 2 +#define IND_SOURCE_BIT 3 + +#define IND_DESTINATION (1 << IND_DESTINATION_BIT) +#define IND_INDIRECTION (1 << IND_INDIRECTION_BIT) +#define IND_DONE (1 << IND_DONE_BIT) +#define IND_SOURCE (1 << IND_SOURCE_BIT) + +#if !defined(__ASSEMBLY__) + #include #ifdef CONFIG_KEXEC @@ -64,10 +76,6 @@ */ typedef unsigned long kimage_entry_t; -#define IND_DESTINATION 0x1 -#define IND_INDIRECTION 0x2 -#define IND_DONE 0x4 -#define IND_SOURCE 0x8 struct kexec_segment { /* @@ -311,4 +319,7 @@ struct task_struct; static inline void crash_kexec(struct pt_regs *regs) { } static inline int kexec_should_crash(struct task_struct *p) { return 0; } #endif /* CONFIG_KEXEC */ + +#endif /* !defined(__ASSEBMLY__) */ + #endif /* LINUX_KEXEC_H */ -- cgit v0.10.2 From b28c2ee868dbdc0baa89c60fb520be85d5e90a72 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Tue, 17 Feb 2015 13:45:58 -0800 Subject: kexec: add IND_FLAGS macro Add a new kexec preprocessor macro IND_FLAGS, which is the bitwise OR of all the possible kexec IND_ kimage_entry indirection flags. Having this macro allows for simplified code in the prosessing of the kexec kimage_entry items. Also, remove the local powerpc definition and use the generic one. Signed-off-by: Geoff Levand Acked-by: Benjamin Herrenschmidt Acked-by: Vivek Goyal Cc: Arnd Bergmann Cc: Maximilian Attems Cc: Michal Marek Cc: H. Peter Anvin Cc: Paul Bolle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index f96d1ec..1a74446 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -96,8 +96,6 @@ int default_machine_kexec_prepare(struct kimage *image) return 0; } -#define IND_FLAGS (IND_DESTINATION | IND_INDIRECTION | IND_DONE | IND_SOURCE) - static void copy_segments(unsigned long ind) { unsigned long entry; diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 1fd980c..e60a745 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -10,6 +10,7 @@ #define IND_INDIRECTION (1 << IND_INDIRECTION_BIT) #define IND_DONE (1 << IND_DONE_BIT) #define IND_SOURCE (1 << IND_SOURCE_BIT) +#define IND_FLAGS (IND_DESTINATION | IND_INDIRECTION | IND_DONE | IND_SOURCE) #if !defined(__ASSEMBLY__) -- cgit v0.10.2 From 34b47764297130b21aaeb4cc6119bb811814b8e3 Mon Sep 17 00:00:00 2001 From: WANG Chao Date: Tue, 17 Feb 2015 13:46:01 -0800 Subject: vmcore: fix PT_NOTE n_namesz, n_descsz overflow issue When updating PT_NOTE header size (ie. p_memsz), an overflow issue happens with the following bogus note entry: n_namesz = 0xFFFFFFFF n_descsz = 0x0 n_type = 0x0 This kind of note entry should be dropped during updating p_memsz. But because n_namesz is 32bit, after (n_namesz + 3) & (~3), it's overflow to 0x0, the note entry size looks sane and reserved. When userspace (eg. crash utility) is trying to access such bogus note, it could lead to an unexpected behavior (eg. crash utility segment fault because it's reading bogus address). The source of bogus note hasn't been identified yet. At least we could drop the bogus note so user space wouldn't be surprised. Signed-off-by: WANG Chao Cc: Dave Anderson Cc: Baoquan He Cc: Randy Wright Cc: Vivek Goyal Cc: Paul Gortmaker Cc: Fabian Frederick Cc: Vitaly Kuznetsov Cc: Rashika Kheria Cc: Greg Pearson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index a90d6d35..4e61388 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -546,8 +546,8 @@ static int __init update_note_header_size_elf64(const Elf64_Ehdr *ehdr_ptr) nhdr_ptr = notes_section; while (nhdr_ptr->n_namesz != 0) { sz = sizeof(Elf64_Nhdr) + - ((nhdr_ptr->n_namesz + 3) & ~3) + - ((nhdr_ptr->n_descsz + 3) & ~3); + (((u64)nhdr_ptr->n_namesz + 3) & ~3) + + (((u64)nhdr_ptr->n_descsz + 3) & ~3); if ((real_sz + sz) > max_sz) { pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n", nhdr_ptr->n_namesz, nhdr_ptr->n_descsz); @@ -732,8 +732,8 @@ static int __init update_note_header_size_elf32(const Elf32_Ehdr *ehdr_ptr) nhdr_ptr = notes_section; while (nhdr_ptr->n_namesz != 0) { sz = sizeof(Elf32_Nhdr) + - ((nhdr_ptr->n_namesz + 3) & ~3) + - ((nhdr_ptr->n_descsz + 3) & ~3); + (((u64)nhdr_ptr->n_namesz + 3) & ~3) + + (((u64)nhdr_ptr->n_descsz + 3) & ~3); if ((real_sz + sz) > max_sz) { pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n", nhdr_ptr->n_namesz, nhdr_ptr->n_descsz); -- cgit v0.10.2 From 7647f14fe4cd98151f8e90656c01fe61044de714 Mon Sep 17 00:00:00 2001 From: John de la Garza Date: Tue, 17 Feb 2015 13:46:04 -0800 Subject: lib/rbtree.c: fix typo in comment Signed-off-by: John de la Garza Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h index 57e75ae..fb31765 100644 --- a/include/linux/rbtree.h +++ b/include/linux/rbtree.h @@ -51,7 +51,7 @@ struct rb_root { #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) -/* 'empty' nodes are nodes that are known not to be inserted in an rbree */ +/* 'empty' nodes are nodes that are known not to be inserted in an rbtree */ #define RB_EMPTY_NODE(node) \ ((node)->__rb_parent_color == (unsigned long)(node)) #define RB_CLEAR_NODE(node) \ -- cgit v0.10.2 From e22553e2a25ed3f2a9c874088e0f20cdcd97c7b0 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Tue, 17 Feb 2015 13:46:07 -0800 Subject: eventfd: don't take the spinlock in eventfd_poll The spinlock in eventfd_poll is trying to protect the count of events so it can decide if it should return POLLIN, POLLERR, or POLLOUT. But, because of the way we drop the lock after calling poll_wait, and drop it again before returning, we have the same pile of races with the lock as we do with a single read of ctx->count(). This replaces the lock with a read barrier and single read. eventfd_write does a single bump of ctx->count, so this should not add new races with adding events. eventfd_read is similar, it will do a single decrement with the lock held, and so we're making the race with concurrent readers slightly larger. This spinlock is the top CPU user in kernel code during one of our workloads. Removing it gives us a ~2% boost. [arnd@arndb.de: avoid unused variable warning] [dan.carpenter@oracle.com: type bug in eventfd_poll()] Signed-off-by: Chris Mason Cc: Davide Libenzi Signed-off-by: Arnd Bergmann Signed-off-by: Dan Carpenter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/eventfd.c b/fs/eventfd.c index 4b0a226..8d0c0df 100644 --- a/fs/eventfd.c +++ b/fs/eventfd.c @@ -118,18 +118,18 @@ static unsigned int eventfd_poll(struct file *file, poll_table *wait) { struct eventfd_ctx *ctx = file->private_data; unsigned int events = 0; - unsigned long flags; + u64 count; poll_wait(file, &ctx->wqh, wait); + smp_rmb(); + count = ctx->count; - spin_lock_irqsave(&ctx->wqh.lock, flags); - if (ctx->count > 0) + if (count > 0) events |= POLLIN; - if (ctx->count == ULLONG_MAX) + if (count == ULLONG_MAX) events |= POLLERR; - if (ULLONG_MAX - 1 > ctx->count) + if (ULLONG_MAX - 1 > count) events |= POLLOUT; - spin_unlock_irqrestore(&ctx->wqh.lock, flags); return events; } -- cgit v0.10.2 From 08fe100d91bc09baca9eb22206f6b050286bd43c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 17 Feb 2015 13:46:10 -0800 Subject: fs/affs: fix casting in printed messages - "inode.i_ino" is "unsigned long", - "loff_t" is always "unsigned long long", - "sector_t" should be cast to "unsigned long long" for printing, - "u32" should not be cast to "unsigned int" for printing. Signed-off-by: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index c852f2f..511ab6b 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c @@ -30,7 +30,7 @@ affs_insert_hash(struct inode *dir, struct buffer_head *bh) ino = bh->b_blocknr; offset = affs_hash_name(sb, AFFS_TAIL(sb, bh)->name + 1, AFFS_TAIL(sb, bh)->name[0]); - pr_debug("%s(dir=%u, ino=%d)\n", __func__, (u32)dir->i_ino, ino); + pr_debug("%s(dir=%lu, ino=%d)\n", __func__, dir->i_ino, ino); dir_bh = affs_bread(sb, dir->i_ino); if (!dir_bh) @@ -80,8 +80,8 @@ affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh) sb = dir->i_sb; rem_ino = rem_bh->b_blocknr; offset = affs_hash_name(sb, AFFS_TAIL(sb, rem_bh)->name+1, AFFS_TAIL(sb, rem_bh)->name[0]); - pr_debug("%s(dir=%d, ino=%d, hashval=%d)\n", - __func__, (u32)dir->i_ino, rem_ino, offset); + pr_debug("%s(dir=%lu, ino=%d, hashval=%d)\n", __func__, dir->i_ino, + rem_ino, offset); bh = affs_bread(sb, dir->i_ino); if (!bh) diff --git a/fs/affs/dir.c b/fs/affs/dir.c index 59f07be..a682892 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c @@ -54,8 +54,7 @@ affs_readdir(struct file *file, struct dir_context *ctx) u32 ino; int error = 0; - pr_debug("%s(ino=%lu,f_pos=%lx)\n", - __func__, inode->i_ino, (unsigned long)ctx->pos); + pr_debug("%s(ino=%lu,f_pos=%llx)\n", __func__, inode->i_ino, ctx->pos); if (ctx->pos < 2) { file->private_data = (void *)0; @@ -117,9 +116,8 @@ inside: namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30); name = AFFS_TAIL(sb, fh_bh)->name + 1; - pr_debug("readdir(): dir_emit(\"%.*s\", " - "ino=%u), hash=%d, f_pos=%x\n", - namelen, name, ino, hash_pos, (u32)ctx->pos); + pr_debug("readdir(): dir_emit(\"%.*s\", ino=%u), hash=%d, f_pos=%llx\n", + namelen, name, ino, hash_pos, ctx->pos); if (!dir_emit(ctx, name, namelen, ino, DT_UNKNOWN)) goto done; diff --git a/fs/affs/file.c b/fs/affs/file.c index 8faa659..40a024a 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -299,8 +299,8 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul struct buffer_head *ext_bh; u32 ext; - pr_debug("%s(%u, %lu)\n", - __func__, (u32)inode->i_ino, (unsigned long)block); + pr_debug("%s(%lu, %llu)\n", __func__, inode->i_ino, + (unsigned long long)block); BUG_ON(block > (sector_t)0x7fffffffUL); @@ -330,8 +330,9 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul /* store new block */ if (bh_result->b_blocknr) - affs_warning(sb, "get_block", "block already set (%lx)", - (unsigned long)bh_result->b_blocknr); + affs_warning(sb, "get_block", + "block already set (%llx)", + (unsigned long long)bh_result->b_blocknr); AFFS_BLOCK(sb, ext_bh, block) = cpu_to_be32(blocknr); AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(block + 1); affs_adjust_checksum(ext_bh, blocknr - bh_result->b_blocknr + 1); @@ -353,8 +354,8 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul return 0; err_big: - affs_error(inode->i_sb, "get_block", "strange block request %d", - (int)block); + affs_error(inode->i_sb, "get_block", "strange block request %llu", + (unsigned long long)block); return -EIO; err_ext: // unlock cache @@ -503,7 +504,7 @@ affs_do_readpage_ofs(struct page *page, unsigned to) u32 bidx, boff, bsize; u32 tmp; - pr_debug("%s(%u, %ld, 0, %d)\n", __func__, (u32)inode->i_ino, + pr_debug("%s(%lu, %ld, 0, %d)\n", __func__, inode->i_ino, page->index, to); BUG_ON(to > PAGE_CACHE_SIZE); kmap(page); @@ -539,7 +540,7 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize) u32 size, bsize; u32 tmp; - pr_debug("%s(%u, %d)\n", __func__, (u32)inode->i_ino, newsize); + pr_debug("%s(%lu, %d)\n", __func__, inode->i_ino, newsize); bsize = AFFS_SB(sb)->s_data_blksize; bh = NULL; size = AFFS_I(inode)->mmu_private; @@ -608,7 +609,7 @@ affs_readpage_ofs(struct file *file, struct page *page) u32 to; int err; - pr_debug("%s(%u, %ld)\n", __func__, (u32)inode->i_ino, page->index); + pr_debug("%s(%lu, %ld)\n", __func__, inode->i_ino, page->index); to = PAGE_CACHE_SIZE; if (((page->index + 1) << PAGE_CACHE_SHIFT) > inode->i_size) { to = inode->i_size & ~PAGE_CACHE_MASK; @@ -631,8 +632,8 @@ static int affs_write_begin_ofs(struct file *file, struct address_space *mapping pgoff_t index; int err = 0; - pr_debug("%s(%u, %llu, %llu)\n", __func__, (u32)inode->i_ino, - (unsigned long long)pos, (unsigned long long)pos + len); + pr_debug("%s(%lu, %llu, %llu)\n", __func__, inode->i_ino, pos, + pos + len); if (pos > AFFS_I(inode)->mmu_private) { /* XXX: this probably leaves a too-big i_size in case of * failure. Should really be updating i_size at write_end time @@ -681,9 +682,8 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping, * due to write_begin. */ - pr_debug("%s(%u, %llu, %llu)\n", - __func__, (u32)inode->i_ino, (unsigned long long)pos, - (unsigned long long)pos + len); + pr_debug("%s(%lu, %llu, %llu)\n", __func__, inode->i_ino, pos, + pos + len); bsize = AFFS_SB(sb)->s_data_blksize; data = page_address(page); @@ -831,8 +831,8 @@ affs_truncate(struct inode *inode) struct buffer_head *ext_bh; int i; - pr_debug("truncate(inode=%d, oldsize=%u, newsize=%u)\n", - (u32)inode->i_ino, (u32)AFFS_I(inode)->mmu_private, (u32)inode->i_size); + pr_debug("truncate(inode=%lu, oldsize=%llu, newsize=%llu)\n", + inode->i_ino, AFFS_I(inode)->mmu_private, inode->i_size); last_blk = 0; ext = 0; @@ -863,7 +863,7 @@ affs_truncate(struct inode *inode) if (IS_ERR(ext_bh)) { affs_warning(sb, "truncate", "unexpected read error for ext block %u (%ld)", - (unsigned int)ext, PTR_ERR(ext_bh)); + ext, PTR_ERR(ext_bh)); return; } if (AFFS_I(inode)->i_lc) { @@ -911,7 +911,7 @@ affs_truncate(struct inode *inode) if (IS_ERR(bh)) { affs_warning(sb, "truncate", "unexpected read error for last block %u (%ld)", - (unsigned int)ext, PTR_ERR(bh)); + ext, PTR_ERR(bh)); return; } tmp = be32_to_cpu(AFFS_DATA_HEAD(bh)->next); diff --git a/fs/affs/inode.c b/fs/affs/inode.c index d0609a2..25cb4b4 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -348,9 +348,8 @@ affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s3 u32 block = 0; int retval; - pr_debug("%s(dir=%u, inode=%u, \"%pd\", type=%d)\n", - __func__, (u32)dir->i_ino, - (u32)inode->i_ino, dentry, type); + pr_debug("%s(dir=%lu, inode=%lu, \"%pd\", type=%d)\n", __func__, + dir->i_ino, inode->i_ino, dentry, type); retval = -EIO; bh = affs_bread(sb, inode->i_ino); diff --git a/fs/affs/namei.c b/fs/affs/namei.c index bbc3853..de84f4d 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -248,9 +248,8 @@ affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) int affs_unlink(struct inode *dir, struct dentry *dentry) { - pr_debug("%s(dir=%d, %lu \"%pd\")\n", - __func__, (u32)dir->i_ino, dentry->d_inode->i_ino, - dentry); + pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino, + dentry->d_inode->i_ino, dentry); return affs_remove_header(dentry); } @@ -317,9 +316,8 @@ affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) int affs_rmdir(struct inode *dir, struct dentry *dentry) { - pr_debug("%s(dir=%u, %lu \"%pd\")\n", - __func__, (u32)dir->i_ino, dentry->d_inode->i_ino, - dentry); + pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino, + dentry->d_inode->i_ino, dentry); return affs_remove_header(dentry); } @@ -404,8 +402,7 @@ affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; - pr_debug("%s(%u, %u, \"%pd\")\n", - __func__, (u32)inode->i_ino, (u32)dir->i_ino, + pr_debug("%s(%lu, %lu, \"%pd\")\n", __func__, inode->i_ino, dir->i_ino, dentry); return affs_add_entry(dir, inode, dentry, ST_LINKFILE); @@ -419,9 +416,8 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry, struct buffer_head *bh = NULL; int retval; - pr_debug("%s(old=%u,\"%pd\" to new=%u,\"%pd\")\n", - __func__, (u32)old_dir->i_ino, old_dentry, - (u32)new_dir->i_ino, new_dentry); + pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__, + old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry); retval = affs_check_name(new_dentry->d_name.name, new_dentry->d_name.len, -- cgit v0.10.2 From afe305dcc96edc06aec923a0f5fa07ff654b2489 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:46:12 -0800 Subject: fs/affs/file.c: replace if/BUG by BUG_ON Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/file.c b/fs/affs/file.c index 40a024a..7e83ba2 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -180,8 +180,7 @@ affs_get_extblock_slow(struct inode *inode, u32 ext) ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension); if (ext < AFFS_I(inode)->i_extcnt) goto read_ext; - if (ext > AFFS_I(inode)->i_extcnt) - BUG(); + BUG_ON(ext > AFFS_I(inode)->i_extcnt); bh = affs_alloc_extblock(inode, bh, ext); if (IS_ERR(bh)) return bh; @@ -198,8 +197,7 @@ affs_get_extblock_slow(struct inode *inode, u32 ext) struct buffer_head *prev_bh; /* allocate a new extended block */ - if (ext > AFFS_I(inode)->i_extcnt) - BUG(); + BUG_ON(ext > AFFS_I(inode)->i_extcnt); /* get previous extended block */ prev_bh = affs_get_extblock(inode, ext - 1); -- cgit v0.10.2 From 92b20708f9f0c6429b3b6865de567e721f509c75 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:46:15 -0800 Subject: fs/affs/file.c: fix direct IO writes beyond EOF Use the same fallback to normal IO in case of write operations beyond EOF as fat direct IO. This patch fixes fsx file -d -Z -r 4096 -w 4096 Report: 129(129 mod 256): TRUNCATE DOWN from 0x3ff01 to 0xb3f6 130(130 mod 256): WRITE 0x22000 thru 0x2dfff (0xc000 bytes) HOLE Thanks to Jan for helping me on this problem. The ideal solution suggested by Jan Kara would be to use cont_write_begin() but affs direct_IO shouldn't be used a lot anyway... Signed-off-by: Fabian Frederick Reviewed-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/file.c b/fs/affs/file.c index 7e83ba2..d2468bf 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -398,6 +398,13 @@ affs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, size_t count = iov_iter_count(iter); ssize_t ret; + if (rw == WRITE) { + loff_t size = offset + count; + + if (AFFS_I(inode)->mmu_private < size) + return 0; + } + ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, affs_get_block); if (ret < 0 && (rw & WRITE)) affs_write_failed(mapping, offset + count); -- cgit v0.10.2 From 4d29e571e1942f8f418bf776af0134a9cb5a35c9 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:46:17 -0800 Subject: fs/affs/super.c: destroy sbi mutex in affs_kill_sb() Call mutex_destroy() on superblock mutex in affs_kill_sb() otherwise mutex debugging code isn't able to detect that mutex is used after being freed. (thanks to Jan Kara for complete definition). Signed-off-by: Fabian Frederick Cc: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/super.c b/fs/affs/super.c index f754ab6..ee8eca7 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -602,6 +602,7 @@ static void affs_kill_sb(struct super_block *sb) affs_free_bitmap(sb); affs_brelse(sbi->s_root_bh); kfree(sbi->s_prefix); + mutex_destroy(&sbi->s_bmlock); kfree(sbi); } } -- cgit v0.10.2 From eeb36f8e938d151fc5e12e96ae13d0e283be357e Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:46:20 -0800 Subject: fs/affs: use unsigned int for string lengths - Some min() were used with different types. - Create a new variable in __affs_hash_dentry() to process affs_check_name()/min() return Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index 511ab6b..0836f6f 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c @@ -508,7 +508,7 @@ affs_check_name(const unsigned char *name, int len, bool notruncate) int affs_copy_name(unsigned char *bstr, struct dentry *dentry) { - int len = min(dentry->d_name.len, 30u); + u32 len = min(dentry->d_name.len, 30u); *bstr++ = len; memcpy(bstr, dentry->d_name.name, len); diff --git a/fs/affs/namei.c b/fs/affs/namei.c index de84f4d..66c6cb3 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -64,15 +64,16 @@ __affs_hash_dentry(struct qstr *qstr, toupper_t toupper, bool notruncate) { const u8 *name = qstr->name; unsigned long hash; - int i; + int retval; + u32 len; - i = affs_check_name(qstr->name, qstr->len, notruncate); - if (i) - return i; + retval = affs_check_name(qstr->name, qstr->len, notruncate); + if (retval) + return retval; hash = init_name_hash(); - i = min(qstr->len, 30u); - for (; i > 0; name++, i--) + len = min(qstr->len, 30u); + for (; len > 0; name++, len--) hash = partial_name_hash(toupper(*name), hash); qstr->hash = end_name_hash(hash); @@ -173,7 +174,7 @@ int affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len) { toupper_t toupper = affs_get_toupper(sb); - int hash; + u32 hash; hash = len = min(len, 30u); for (; len > 0; len--) -- cgit v0.10.2 From f157853e407c0611cd6acbc400fa6c7be420b1bd Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:46:23 -0800 Subject: fs/affs: define AFFSNAMEMAX to replace constant use 30 was used all over the place to compare name length against AFFS maximum name length. Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/affs.h b/fs/affs/affs.h index ff44ff3..c8764bd 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h @@ -30,6 +30,8 @@ #define AFFS_AC_SIZE (AFFS_CACHE_SIZE/sizeof(struct affs_ext_key)/2) #define AFFS_AC_MASK (AFFS_AC_SIZE-1) +#define AFFSNAMEMAX 30U + struct affs_ext_key { u32 ext; /* idx of the extended block */ u32 key; /* block number */ diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index 0836f6f..118d782 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c @@ -483,11 +483,11 @@ affs_check_name(const unsigned char *name, int len, bool notruncate) { int i; - if (len > 30) { + if (len > AFFSNAMEMAX) { if (notruncate) return -ENAMETOOLONG; else - len = 30; + len = AFFSNAMEMAX; } for (i = 0; i < len; i++) { if (name[i] < ' ' || name[i] == ':' @@ -508,7 +508,7 @@ affs_check_name(const unsigned char *name, int len, bool notruncate) int affs_copy_name(unsigned char *bstr, struct dentry *dentry) { - u32 len = min(dentry->d_name.len, 30u); + u32 len = min(dentry->d_name.len, AFFSNAMEMAX); *bstr++ = len; memcpy(bstr, dentry->d_name.name, len); diff --git a/fs/affs/dir.c b/fs/affs/dir.c index a682892..ac4f318 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c @@ -114,7 +114,8 @@ inside: break; } - namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30); + namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], + (u8)AFFSNAMEMAX); name = AFFS_TAIL(sb, fh_bh)->name + 1; pr_debug("readdir(): dir_emit(\"%.*s\", ino=%u), hash=%d, f_pos=%llx\n", namelen, name, ino, hash_pos, ctx->pos); diff --git a/fs/affs/namei.c b/fs/affs/namei.c index 66c6cb3..ffb7bd8 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -72,7 +72,7 @@ __affs_hash_dentry(struct qstr *qstr, toupper_t toupper, bool notruncate) return retval; hash = init_name_hash(); - len = min(qstr->len, 30u); + len = min(qstr->len, AFFSNAMEMAX); for (; len > 0; name++, len--) hash = partial_name_hash(toupper(*name), hash); qstr->hash = end_name_hash(hash); @@ -115,10 +115,10 @@ static inline int __affs_compare_dentry(unsigned int len, * If the names are longer than the allowed 30 chars, * the excess is ignored, so their length may differ. */ - if (len >= 30) { - if (name->len < 30) + if (len >= AFFSNAMEMAX) { + if (name->len < AFFSNAMEMAX) return 1; - len = 30; + len = AFFSNAMEMAX; } else if (len != name->len) return 1; @@ -157,10 +157,10 @@ affs_match(struct dentry *dentry, const u8 *name2, toupper_t toupper) const u8 *name = dentry->d_name.name; int len = dentry->d_name.len; - if (len >= 30) { - if (*name2 < 30) + if (len >= AFFSNAMEMAX) { + if (*name2 < AFFSNAMEMAX) return 0; - len = 30; + len = AFFSNAMEMAX; } else if (len != *name2) return 0; @@ -176,7 +176,7 @@ affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len) toupper_t toupper = affs_get_toupper(sb); u32 hash; - hash = len = min(len, 30u); + hash = len = min(len, AFFSNAMEMAX); for (; len > 0; len--) hash = (hash * 13 + toupper(*name++)) & 0x7ff; diff --git a/fs/affs/super.c b/fs/affs/super.c index ee8eca7..c3524bf 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -584,7 +584,7 @@ affs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_bavail = free; buf->f_fsid.val[0] = (u32)id; buf->f_fsid.val[1] = (u32)(id >> 32); - buf->f_namelen = 30; + buf->f_namelen = AFFSNAMEMAX; return 0; } -- cgit v0.10.2 From b4478e3530288503704e1cc701c426174e4550f0 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:46:25 -0800 Subject: fs/affs/amigaffs.c: remove else after return else is unnecessary after return -ENAMETOOLONG Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index 118d782..388da1e 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c @@ -486,8 +486,7 @@ affs_check_name(const unsigned char *name, int len, bool notruncate) if (len > AFFSNAMEMAX) { if (notruncate) return -ENAMETOOLONG; - else - len = AFFSNAMEMAX; + len = AFFSNAMEMAX; } for (i = 0; i < len; i++) { if (name[i] < ' ' || name[i] == ':' -- cgit v0.10.2 From 211c2af014d2c41752a13b652ae8b9815e07802c Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:46:28 -0800 Subject: fs/affs/bitmap.c: remove unnecessary return return is not needed at the end of function. Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c index c8de511..6751489 100644 --- a/fs/affs/bitmap.c +++ b/fs/affs/bitmap.c @@ -99,7 +99,6 @@ err_bh_read: err_range: affs_error(sb, "affs_free_block","Block %u outside partition", block); - return; } /* -- cgit v0.10.2 From 0cdfe18ad5ae0fbb9417ac2b5808189aaaa54230 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:46:30 -0800 Subject: fs/affs/inode.c: remove double extern affs_symlink_inode_operations affs_symlink_inode_operations was already declared extern in affs.h Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 25cb4b4..6f34510 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -13,8 +13,6 @@ #include #include "affs.h" -extern const struct inode_operations affs_symlink_inode_operations; - struct inode *affs_iget(struct super_block *sb, unsigned long ino) { struct affs_sb_info *sbi = AFFS_SB(sb); -- cgit v0.10.2 From 0445f01a53ad53ef6b23307b4630ab92423994ab Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 17 Feb 2015 13:46:33 -0800 Subject: fs/affs/super.c: fix switch indentation Fix checkpatch error: ERROR: switch and case should be at the same indent Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/super.c b/fs/affs/super.c index c3524bf..4cf0e91 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -432,39 +432,39 @@ got_root: sb->s_flags |= MS_RDONLY; } switch (chksum) { - case MUFS_FS: - case MUFS_INTLFFS: - case MUFS_DCFFS: - sbi->s_flags |= SF_MUFS; - /* fall thru */ - case FS_INTLFFS: - case FS_DCFFS: - sbi->s_flags |= SF_INTL; - break; - case MUFS_FFS: - sbi->s_flags |= SF_MUFS; - break; - case FS_FFS: - break; - case MUFS_OFS: - sbi->s_flags |= SF_MUFS; - /* fall thru */ - case FS_OFS: - sbi->s_flags |= SF_OFS; - sb->s_flags |= MS_NOEXEC; - break; - case MUFS_DCOFS: - case MUFS_INTLOFS: - sbi->s_flags |= SF_MUFS; - case FS_DCOFS: - case FS_INTLOFS: - sbi->s_flags |= SF_INTL | SF_OFS; - sb->s_flags |= MS_NOEXEC; - break; - default: - pr_err("Unknown filesystem on device %s: %08X\n", - sb->s_id, chksum); - return -EINVAL; + case MUFS_FS: + case MUFS_INTLFFS: + case MUFS_DCFFS: + sbi->s_flags |= SF_MUFS; + /* fall thru */ + case FS_INTLFFS: + case FS_DCFFS: + sbi->s_flags |= SF_INTL; + break; + case MUFS_FFS: + sbi->s_flags |= SF_MUFS; + break; + case FS_FFS: + break; + case MUFS_OFS: + sbi->s_flags |= SF_MUFS; + /* fall thru */ + case FS_OFS: + sbi->s_flags |= SF_OFS; + sb->s_flags |= MS_NOEXEC; + break; + case MUFS_DCOFS: + case MUFS_INTLOFS: + sbi->s_flags |= SF_MUFS; + case FS_DCOFS: + case FS_INTLOFS: + sbi->s_flags |= SF_INTL | SF_OFS; + sb->s_flags |= MS_NOEXEC; + break; + default: + pr_err("Unknown filesystem on device %s: %08X\n", + sb->s_id, chksum); + return -EINVAL; } if (mount_flags & SF_VERBOSE) { -- cgit v0.10.2 From 3ee7b3fa2cd0182628cca8d9bb5ce2d4722e8dc5 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:46:36 -0800 Subject: scripts/gdb: add infrastructure This provides the basic infrastructure to load kernel-specific python helper scripts when debugging the kernel in gdb. The loading mechanism is based on gdb loading for -gdb.py when opening . Therefore, this places a corresponding link to the main helper script into the output directory that contains vmlinux. The main scripts will pull in submodules containing Linux specific gdb commands and functions. To avoid polluting the source directory with compiled python modules, we link to them from the object directory. Due to gdb.parse_and_eval and string redirection for gdb.execute, we depend on gdb >= 7.2. This feature is enabled via CONFIG_GDB_SCRIPTS. Signed-off-by: Jan Kiszka Acked-by: Michal Marek [kbuild stuff] Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Makefile b/Makefile index 33cb15e..dd8796c 100644 --- a/Makefile +++ b/Makefile @@ -927,6 +927,9 @@ endif ifdef CONFIG_BUILD_DOCSRC $(Q)$(MAKE) $(build)=Documentation endif +ifdef CONFIG_GDB_SCRIPTS + $(Q)ln -fsn `cd $(srctree) && /bin/pwd`/scripts/gdb/vmlinux-gdb.py +endif +$(call if_changed,link-vmlinux) # The actual objects are generated when descending, @@ -1181,7 +1184,7 @@ MRPROPER_FILES += .config .config.old .version .old_version $(version_h) \ 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 + signing_key.x509.signer vmlinux-gdb.py # clean - Delete most, but leave enough to build external modules # diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ecb3516..c5cefb3 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -167,6 +167,17 @@ config DEBUG_INFO_DWARF4 But it significantly improves the success of resolving variables in gdb on optimized code. +config GDB_SCRIPTS + bool "Provide GDB scripts for kernel debugging" + depends on DEBUG_INFO + help + This creates the required links to GDB helper scripts in the + build directory. If you load vmlinux into gdb, the helper + scripts will be automatically imported by gdb as well, and + additional functions are available to analyze a Linux kernel + instance. See Documentation/gdb-kernel-debugging.txt for further + details. + config ENABLE_WARN_DEPRECATED bool "Enable __deprecated logic" default y diff --git a/scripts/Makefile b/scripts/Makefile index 72902b5..2016a64 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -36,6 +36,7 @@ subdir-$(CONFIG_MODVERSIONS) += genksyms subdir-y += mod subdir-$(CONFIG_SECURITY_SELINUX) += selinux subdir-$(CONFIG_DTC) += dtc +subdir-$(CONFIG_GDB_SCRIPTS) += gdb # Let clean descend into subdirs subdir- += basic kconfig package diff --git a/scripts/gdb/Makefile b/scripts/gdb/Makefile new file mode 100644 index 0000000..62f5f65 --- /dev/null +++ b/scripts/gdb/Makefile @@ -0,0 +1 @@ +subdir-y := linux diff --git a/scripts/gdb/linux/Makefile b/scripts/gdb/linux/Makefile new file mode 100644 index 0000000..6cf1ecf --- /dev/null +++ b/scripts/gdb/linux/Makefile @@ -0,0 +1,11 @@ +always := gdb-scripts + +SRCTREE := $(shell cd $(srctree) && /bin/pwd) + +$(obj)/gdb-scripts: +ifneq ($(KBUILD_SRC),) + $(Q)ln -fsn $(SRCTREE)/$(obj)/*.py $(objtree)/$(obj) +endif + @: + +clean-files := *.pyc *.pyo $(if $(KBUILD_SRC),*.py) diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py new file mode 100644 index 0000000..c1d90ce --- /dev/null +++ b/scripts/gdb/vmlinux-gdb.py @@ -0,0 +1,23 @@ +# +# gdb helper commands and functions for Linux kernel debugging +# +# loader module +# +# Copyright (c) Siemens AG, 2012, 2013 +# +# Authors: +# Jan Kiszka +# +# This work is licensed under the terms of the GNU GPL version 2. +# + +import os + +sys.path.insert(0, os.path.dirname(__file__) + "/scripts/gdb") + +try: + gdb.parse_and_eval("0") + gdb.execute("", to_string=True) +except: + gdb.write("NOTE: gdb 7.2 or later required for Linux helper scripts to " + "work.\n") -- cgit v0.10.2 From 2b514827ef06fd69e1739e7f367712619dee7784 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:46:38 -0800 Subject: scripts/gdb: add cache for type objects Type lookups are very slow in gdb-python which is often noticeable when iterating over a number of objects. Introduce the helper class CachedType that keeps a reference to a gdb.Type object but also refreshes it after an object file has been loaded. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py new file mode 100644 index 0000000..f883611 --- /dev/null +++ b/scripts/gdb/linux/utils.py @@ -0,0 +1,34 @@ +# +# gdb helper commands and functions for Linux kernel debugging +# +# common utilities +# +# Copyright (c) Siemens AG, 2011-2013 +# +# Authors: +# Jan Kiszka +# +# This work is licensed under the terms of the GNU GPL version 2. +# + +import gdb + + +class CachedType: + def __init__(self, name): + self._type = None + self._name = name + + def _new_objfile_handler(self, event): + self._type = None + gdb.events.new_objfile.disconnect(self._new_objfile_handler) + + def get_type(self): + if self._type is None: + self._type = gdb.lookup_type(self._name) + if self._type is None: + raise gdb.GdbError( + "cannot resolve type '{0}'".format(self._name)) + if hasattr(gdb, 'events') and hasattr(gdb.events, 'new_objfile'): + gdb.events.new_objfile.connect(self._new_objfile_handler) + return self._type -- cgit v0.10.2 From b0fecd8c570310c5041035a94eda7a4610402ace Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:46:41 -0800 Subject: scripts/gdb: add container_of helper and convenience function Provide an internal helper with container_of semantics. As type lookups are very slow in gdb-python and we need a type "long" for this, cache the reference to this type object. Then export the helper also as a convenience function form use at the gdb command line. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py index f883611..c9d705b 100644 --- a/scripts/gdb/linux/utils.py +++ b/scripts/gdb/linux/utils.py @@ -32,3 +32,38 @@ class CachedType: if hasattr(gdb, 'events') and hasattr(gdb.events, 'new_objfile'): gdb.events.new_objfile.connect(self._new_objfile_handler) return self._type + + +long_type = CachedType("long") + + +def get_long_type(): + global long_type + return long_type.get_type() + + +def offset_of(typeobj, field): + element = gdb.Value(0).cast(typeobj) + return int(str(element[field].address).split()[0], 16) + + +def container_of(ptr, typeobj, member): + return (ptr.cast(get_long_type()) - + offset_of(typeobj, member)).cast(typeobj) + + +class ContainerOf(gdb.Function): + """Return pointer to containing data structure. + +$container_of(PTR, "TYPE", "ELEMENT"): Given PTR, return a pointer to the +data structure of the type TYPE in which PTR is the address of ELEMENT. +Note that TYPE and ELEMENT have to be quoted as strings.""" + + def __init__(self): + super(ContainerOf, self).__init__("container_of") + + def invoke(self, ptr, typename, elementname): + return container_of(ptr, gdb.lookup_type(typename.string()).pointer(), + elementname.string()) + +ContainerOf() diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py index c1d90ce..6495841 100644 --- a/scripts/gdb/vmlinux-gdb.py +++ b/scripts/gdb/vmlinux-gdb.py @@ -21,3 +21,5 @@ try: except: gdb.write("NOTE: gdb 7.2 or later required for Linux helper scripts to " "work.\n") +else: + import linux.utils -- cgit v0.10.2 From 850202e17df68c51593bab36a26c8d9279f8c029 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:46:44 -0800 Subject: scripts/gdb: add module iteration class Will soon be used for loading symbols, printing global variables or listing modules. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py new file mode 100644 index 0000000..8a65c3d --- /dev/null +++ b/scripts/gdb/linux/modules.py @@ -0,0 +1,39 @@ +# +# gdb helper commands and functions for Linux kernel debugging +# +# module tools +# +# Copyright (c) Siemens AG, 2013 +# +# Authors: +# Jan Kiszka +# +# This work is licensed under the terms of the GNU GPL version 2. +# + +import gdb + +from linux import utils + + +module_type = utils.CachedType("struct module") + + +class ModuleList: + def __init__(self): + global module_type + self.module_ptr_type = module_type.get_type().pointer() + modules = gdb.parse_and_eval("modules") + self.curr_entry = modules['next'] + self.end_of_list = modules.address + + def __iter__(self): + return self + + def next(self): + entry = self.curr_entry + if entry != self.end_of_list: + self.curr_entry = entry['next'] + return utils.container_of(entry, self.module_ptr_type, "list") + else: + raise StopIteration -- cgit v0.10.2 From 66051720b84127cac32f34a30c91390c0ebf898f Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:46:47 -0800 Subject: scripts/gdb: add lx-symbols command This is probably the most useful helper when debugging kernel modules: lx-symbols first reloads vmlinux. Then it searches recursively for *.ko files in the specified paths and the current directory. Finally it walks the kernel's module list, issuing the necessary add-symbol-file command for each loaded module so that gdb knows which module symbol corresponds to which address. It also looks up variable sections (bss, data, rodata) and appends their address to the add-symbole-file command line. This allows to access global module variables just like any other variable. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py new file mode 100644 index 0000000..bd21a96 --- /dev/null +++ b/scripts/gdb/linux/symbols.py @@ -0,0 +1,127 @@ +# +# gdb helper commands and functions for Linux kernel debugging +# +# load kernel and module symbols +# +# Copyright (c) Siemens AG, 2011-2013 +# +# Authors: +# Jan Kiszka +# +# This work is licensed under the terms of the GNU GPL version 2. +# + +import gdb +import os +import re +import string + +from linux import modules, utils + + +class LxSymbols(gdb.Command): + """(Re-)load symbols of Linux kernel and currently loaded modules. + +The kernel (vmlinux) is taken from the current working directly. Modules (.ko) +are scanned recursively, starting in the same directory. Optionally, the module +search path can be extended by a space separated list of paths passed to the +lx-symbols command.""" + + module_paths = [] + module_files = [] + module_files_updated = False + + def __init__(self): + super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES, + gdb.COMPLETE_FILENAME) + + def _update_module_files(self): + self.module_files = [] + for path in self.module_paths: + gdb.write("scanning for modules in {0}\n".format(path)) + for root, dirs, files in os.walk(path): + for name in files: + if name.endswith(".ko"): + self.module_files.append(root + "/" + name) + self.module_files_updated = True + + def _get_module_file(self, module_name): + module_pattern = ".*/{0}\.ko$".format( + string.replace(module_name, "_", r"[_\-]")) + for name in self.module_files: + if re.match(module_pattern, name) and os.path.exists(name): + return name + return None + + def _section_arguments(self, module): + try: + sect_attrs = module['sect_attrs'].dereference() + except gdb.error: + return "" + attrs = sect_attrs['attrs'] + section_name_to_address = { + attrs[n]['name'].string() : attrs[n]['address'] + for n in range(sect_attrs['nsections'])} + args = [] + for section_name in [".data", ".data..read_mostly", ".rodata", ".bss"]: + address = section_name_to_address.get(section_name) + if address: + args.append(" -s {name} {addr}".format( + name=section_name, addr=str(address))) + return "".join(args) + + def load_module_symbols(self, module): + module_name = module['name'].string() + module_addr = str(module['module_core']).split()[0] + + module_file = self._get_module_file(module_name) + if not module_file and not self.module_files_updated: + self._update_module_files() + module_file = self._get_module_file(module_name) + + if module_file: + gdb.write("loading @{addr}: {filename}\n".format( + addr=module_addr, filename=module_file)) + cmdline = "add-symbol-file {filename} {addr}{sections}".format( + filename=module_file, + addr=module_addr, + sections=self._section_arguments(module)) + gdb.execute(cmdline, to_string=True) + else: + gdb.write("no module object found for '{0}'\n".format(module_name)) + + def load_all_symbols(self): + gdb.write("loading vmlinux\n") + + # Dropping symbols will disable all breakpoints. So save their states + # and restore them afterward. + saved_states = [] + if hasattr(gdb, 'breakpoints') and not gdb.breakpoints() is None: + for bp in gdb.breakpoints(): + saved_states.append({'breakpoint': bp, 'enabled': bp.enabled}) + + # drop all current symbols and reload vmlinux + gdb.execute("symbol-file", to_string=True) + gdb.execute("symbol-file vmlinux") + + module_list = modules.ModuleList() + if not module_list: + gdb.write("no modules found\n") + else: + [self.load_module_symbols(module) for module in module_list] + + for saved_state in saved_states: + saved_state['breakpoint'].enabled = saved_state['enabled'] + + def invoke(self, arg, from_tty): + self.module_paths = arg.split() + self.module_paths.append(os.getcwd()) + + # enforce update + self.module_files = [] + self.module_files_updated = False + + self.load_all_symbols() + + +LxSymbols() diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py index 6495841..0b0faa4 100644 --- a/scripts/gdb/vmlinux-gdb.py +++ b/scripts/gdb/vmlinux-gdb.py @@ -23,3 +23,4 @@ except: "work.\n") else: import linux.utils + import linux.symbols -- cgit v0.10.2 From be02a1862304b126cd6ba4f347fa5db59460a776 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:46:50 -0800 Subject: kernel/module.c: do not inline do_init_module() This provides a reliable breakpoint target, required for automatic symbol loading via the gdb helper command 'lx-symbols'. Signed-off-by: Jan Kiszka Acked-by: Rusty Russell Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/module.c b/kernel/module.c index 8426ad4..b34813f 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -3025,8 +3025,13 @@ static void do_free_init(struct rcu_head *head) kfree(m); } -/* This is where the real work happens */ -static int do_init_module(struct module *mod) +/* + * This is where the real work happens. + * + * Keep it uninlined to provide a reliable breakpoint target, e.g. for the gdb + * helper command 'lx-symbols'. + */ +static noinline int do_init_module(struct module *mod) { int ret = 0; struct mod_initfree *freeinit; -- cgit v0.10.2 From 82b41e3d6113291258c65281144bce946553dfed Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:46:52 -0800 Subject: scripts/gdb: add automatic symbol reloading on module insertion This installs a silent breakpoint on the do_init_module function. The breakpoint handler will try to load symbols from the module files found during lx-symbols execution. This way, breakpoints can be set to module initialization functions, and there is no need to explicitly call lx-symbols after (re-)loading a module. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py index bd21a96..139841f 100644 --- a/scripts/gdb/linux/symbols.py +++ b/scripts/gdb/linux/symbols.py @@ -19,6 +19,30 @@ import string from linux import modules, utils +if hasattr(gdb, 'Breakpoint'): + class LoadModuleBreakpoint(gdb.Breakpoint): + def __init__(self, spec, gdb_command): + super(LoadModuleBreakpoint, self).__init__(spec, internal=True) + self.silent = True + self.gdb_command = gdb_command + + def stop(self): + module = gdb.parse_and_eval("mod") + module_name = module['name'].string() + cmd = self.gdb_command + + # enforce update if object file is not found + cmd.module_files_updated = False + + if module_name in cmd.loaded_modules: + gdb.write("refreshing all symbols to reload module " + "'{0}'\n".format(module_name)) + cmd.load_all_symbols() + else: + cmd.load_module_symbols(module) + return False + + class LxSymbols(gdb.Command): """(Re-)load symbols of Linux kernel and currently loaded modules. @@ -30,6 +54,8 @@ lx-symbols command.""" module_paths = [] module_files = [] module_files_updated = False + loaded_modules = [] + breakpoint = None def __init__(self): super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES, @@ -87,6 +113,8 @@ lx-symbols command.""" addr=module_addr, sections=self._section_arguments(module)) gdb.execute(cmdline, to_string=True) + if not module_name in self.loaded_modules: + self.loaded_modules.append(module_name) else: gdb.write("no module object found for '{0}'\n".format(module_name)) @@ -104,6 +132,7 @@ lx-symbols command.""" gdb.execute("symbol-file", to_string=True) gdb.execute("symbol-file vmlinux") + self.loaded_modules = [] module_list = modules.ModuleList() if not module_list: gdb.write("no modules found\n") @@ -123,5 +152,15 @@ lx-symbols command.""" self.load_all_symbols() + if hasattr(gdb, 'Breakpoint'): + if not self.breakpoint is None: + self.breakpoint.delete() + self.breakpoint = None + self.breakpoint = LoadModuleBreakpoint( + "kernel/module.c:do_init_module", self) + else: + gdb.write("Note: symbol update on module loading not supported " + "with this gdb version\n") + LxSymbols() -- cgit v0.10.2 From 7b599ef535a7faef53034fb7fb150b61057efe28 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:46:55 -0800 Subject: scripts/gdb: add internal helper and convenience function to look up a module Add the internal helper get_module_by_name to obtain the module structure corresponding to the given name. Also export this service as a convenience function. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py index 8a65c3d..531f763 100644 --- a/scripts/gdb/linux/modules.py +++ b/scripts/gdb/linux/modules.py @@ -37,3 +37,31 @@ class ModuleList: return utils.container_of(entry, self.module_ptr_type, "list") else: raise StopIteration + + +def find_module_by_name(name): + for module in ModuleList(): + if module['name'].string() == name: + return module + return None + + +class LxModule(gdb.Function): + """Find module by name and return the module variable. + +$lx_module("MODULE"): Given the name MODULE, iterate over all loaded modules +of the target and return that module variable which MODULE matches.""" + + def __init__(self): + super(LxModule, self).__init__("lx_module") + + def invoke(self, mod_name): + mod_name = mod_name.string() + module = find_module_by_name(mod_name) + if module: + return module.dereference() + else: + raise gdb.GdbError("Unable to find MODULE " + mod_name) + + +LxModule() diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py index 0b0faa4..cf2e716 100644 --- a/scripts/gdb/vmlinux-gdb.py +++ b/scripts/gdb/vmlinux-gdb.py @@ -24,3 +24,4 @@ except: else: import linux.utils import linux.symbols + import linux.modules -- cgit v0.10.2 From 7f994963745b9cea89a2816dae7cc3a1fc01adcc Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:46:58 -0800 Subject: scripts/gdb: add get_target_endianness helper Parse the target endianness from the output of "show endian" and cache the result to return it via the new helper get_target_endiannes. We will need it for reading integers from buffers that contain target memory. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py index c9d705b..10a227b 100644 --- a/scripts/gdb/linux/utils.py +++ b/scripts/gdb/linux/utils.py @@ -67,3 +67,21 @@ Note that TYPE and ELEMENT have to be quoted as strings.""" elementname.string()) ContainerOf() + + +BIG_ENDIAN = 0 +LITTLE_ENDIAN = 1 +target_endianness = None + + +def get_target_endianness(): + global target_endianness + if target_endianness is None: + endian = gdb.execute("show endian", to_string=True) + if "little endian" in endian: + target_endianness = LITTLE_ENDIAN + elif "big endian" in endian: + target_endianness = BIG_ENDIAN + else: + raise gdb.GdgError("unknown endianness '{0}'".format(endian)) + return target_endianness -- cgit v0.10.2 From 78e878172327b1b6aa6264b1d22f9a083f9ddaa6 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:01 -0800 Subject: scripts/gdb: add read_u16/32/64 helpers Add helpers for reading integers from target memory buffers. Required when caching the memory access is more efficient than reading individual values via gdb. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py index 10a227b..808a265 100644 --- a/scripts/gdb/linux/utils.py +++ b/scripts/gdb/linux/utils.py @@ -85,3 +85,24 @@ def get_target_endianness(): else: raise gdb.GdgError("unknown endianness '{0}'".format(endian)) return target_endianness + + +def read_u16(buffer): + if get_target_endianness() == LITTLE_ENDIAN: + return ord(buffer[0]) + (ord(buffer[1]) << 8) + else: + return ord(buffer[1]) + (ord(buffer[0]) << 8) + + +def read_u32(buffer): + if get_target_endianness() == LITTLE_ENDIAN: + return read_u16(buffer[0:2]) + (read_u16(buffer[2:4]) << 16) + else: + return read_u16(buffer[2:4]) + (read_u16(buffer[0:2]) << 16) + + +def read_u64(buffer): + if get_target_endianness() == LITTLE_ENDIAN: + return read_u32(buffer[0:4]) + (read_u32(buffer[4:8]) << 32) + else: + return read_u32(buffer[4:8]) + (read_u32(buffer[0:4]) << 32) -- cgit v0.10.2 From ae7dbaad23f0346dc4e2476be63a9a5a376ee472 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:04 -0800 Subject: scripts/gdb: add lx-dmesg command This pokes into the log buffer of the debugged kernel, dumping it to the gdb console. Helping in case the target should or can no longer execute dmesg itself. Signed-off-by: Jan Kiszka Cc: Kay Sievers Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py new file mode 100644 index 0000000..7650f24 --- /dev/null +++ b/scripts/gdb/linux/dmesg.py @@ -0,0 +1,64 @@ +# +# gdb helper commands and functions for Linux kernel debugging +# +# kernel log buffer dump +# +# Copyright (c) Siemens AG, 2011, 2012 +# +# Authors: +# Jan Kiszka +# +# This work is licensed under the terms of the GNU GPL version 2. +# + +import gdb +import string + +from linux import utils + + +class LxDmesg(gdb.Command): + """Print Linux kernel log buffer.""" + + def __init__(self): + super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA) + + def invoke(self, arg, from_tty): + log_buf_addr = int(str(gdb.parse_and_eval("log_buf")).split()[0], 16) + log_first_idx = int(gdb.parse_and_eval("log_first_idx")) + log_next_idx = int(gdb.parse_and_eval("log_next_idx")) + log_buf_len = int(gdb.parse_and_eval("log_buf_len")) + + inf = gdb.inferiors()[0] + start = log_buf_addr + log_first_idx + if log_first_idx < log_next_idx: + log_buf_2nd_half = -1 + length = log_next_idx - log_first_idx + log_buf = inf.read_memory(start, length) + else: + log_buf_2nd_half = log_buf_len - log_first_idx + log_buf = inf.read_memory(start, log_buf_2nd_half) + \ + inf.read_memory(log_buf_addr, log_next_idx) + + pos = 0 + while pos < log_buf.__len__(): + length = utils.read_u16(log_buf[pos + 8:pos + 10]) + if length == 0: + if log_buf_2nd_half == -1: + gdb.write("Corrupted log buffer!\n") + break + pos = log_buf_2nd_half + continue + + text_len = utils.read_u16(log_buf[pos + 10:pos + 12]) + time_stamp = utils.read_u64(log_buf[pos:pos + 8]) + + for line in log_buf[pos + 16:pos + 16 + text_len].splitlines(): + gdb.write("[{time:12.6f}] {line}\n".format( + time=time_stamp / 1000000000.0, + line=line)) + + pos += length + + +LxDmesg() diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py index cf2e716..fa66d23 100644 --- a/scripts/gdb/vmlinux-gdb.py +++ b/scripts/gdb/vmlinux-gdb.py @@ -25,3 +25,4 @@ else: import linux.utils import linux.symbols import linux.modules + import linux.dmesg -- cgit v0.10.2 From 7704d58a8509c65e3f7e4407ca2e5fa6360349c1 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:07 -0800 Subject: scripts/gdb: add task iteration class This class allows to iterate over all tasks of the target. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py new file mode 100644 index 0000000..cd25984 --- /dev/null +++ b/scripts/gdb/linux/tasks.py @@ -0,0 +1,46 @@ +# +# gdb helper commands and functions for Linux kernel debugging +# +# task & thread tools +# +# Copyright (c) Siemens AG, 2011-2013 +# +# Authors: +# Jan Kiszka +# +# This work is licensed under the terms of the GNU GPL version 2. +# + +import gdb + +from linux import utils + + +task_type = utils.CachedType("struct task_struct") + + +class TaskList: + def __init__(self): + global task_type + self.task_ptr_type = task_type.get_type().pointer() + self.init_task = gdb.parse_and_eval("init_task") + self.curr_group = self.init_task.address + self.curr_task = None + + def __iter__(self): + return self + + def next(self): + t = self.curr_task + if not t or t == self.curr_group: + self.curr_group = \ + utils.container_of(self.curr_group['tasks']['next'], + self.task_ptr_type, "tasks") + if self.curr_group == self.init_task.address: + raise StopIteration + t = self.curr_task = self.curr_group + else: + self.curr_task = \ + utils.container_of(t['thread_group']['next'], + self.task_ptr_type, "thread_group") + return t -- cgit v0.10.2 From 4752871081ba4fbb3c539488a95e77d8011bfe49 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:10 -0800 Subject: scripts/gdb: add helper and convenience function to look up tasks Add the helper task_by_pid that can look up a task by its PID. Also export it as a convenience function. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py index cd25984..13bb97c 100644 --- a/scripts/gdb/linux/tasks.py +++ b/scripts/gdb/linux/tasks.py @@ -44,3 +44,30 @@ class TaskList: utils.container_of(t['thread_group']['next'], self.task_ptr_type, "thread_group") return t + + +def get_task_by_pid(pid): + for task in TaskList(): + if int(task['pid']) == pid: + return task + return None + + +class LxTaskByPidFunc(gdb.Function): + """Find Linux task by PID and return the task_struct variable. + +$lx_task_by_pid(PID): Given PID, iterate over all tasks of the target and +return that task_struct variable which PID matches.""" + + def __init__(self): + super(LxTaskByPidFunc, self).__init__("lx_task_by_pid") + + def invoke(self, pid): + task = get_task_by_pid(pid) + if task: + return task.dereference() + else: + raise gdb.GdbError("No task of PID " + str(pid)) + + +LxTaskByPidFunc() diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py index fa66d23..4d7eb2c 100644 --- a/scripts/gdb/vmlinux-gdb.py +++ b/scripts/gdb/vmlinux-gdb.py @@ -26,3 +26,4 @@ else: import linux.symbols import linux.modules import linux.dmesg + import linux.tasks -- cgit v0.10.2 From b24e2d21ac6efd23a67652870fac0cfb943d2264 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:12 -0800 Subject: scripts/gdb: add is_target_arch helper This helper caches to result of "show architecture" and matches the provided arch (sub-)string against that output. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py index 808a265..71ee48c 100644 --- a/scripts/gdb/linux/utils.py +++ b/scripts/gdb/linux/utils.py @@ -106,3 +106,16 @@ def read_u64(buffer): return read_u32(buffer[0:4]) + (read_u32(buffer[4:8]) << 32) else: return read_u32(buffer[4:8]) + (read_u32(buffer[0:4]) << 32) + + +target_arch = None + + +def is_target_arch(arch): + if hasattr(gdb.Frame, 'architecture'): + return arch in gdb.newest_frame().architecture().name() + else: + global target_arch + if target_arch is None: + target_arch = gdb.execute("show architecture", to_string=True) + return arch in target_arch -- cgit v0.10.2 From cf7492e933c0df200f8fa46c3684e8bd20890ab2 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:15 -0800 Subject: scripts/gdb: add internal helper and convenience function to retrieve thread_info Add the internal helper get_thread_info that calculates the thread_info from a given task variable. Also export this service as a convenience function. Note: ia64 version is untested. Signed-off-by: Jan Kiszka Cc: Tony Luck Cc: Fenghua Yu Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py index 13bb97c..63cd6c5 100644 --- a/scripts/gdb/linux/tasks.py +++ b/scripts/gdb/linux/tasks.py @@ -71,3 +71,38 @@ return that task_struct variable which PID matches.""" LxTaskByPidFunc() + + +thread_info_type = utils.CachedType("struct thread_info") + +ia64_task_size = None + + +def get_thread_info(task): + global thread_info_type + thread_info_ptr_type = thread_info_type.get_type().pointer() + if utils.is_target_arch("ia64"): + global ia64_task_size + if ia64_task_size is None: + ia64_task_size = gdb.parse_and_eval("sizeof(struct task_struct)") + thread_info_addr = task.address + ia64_task_size + thread_info = thread_info_addr.cast(thread_info_ptr_type) + else: + thread_info = task['stack'].cast(thread_info_ptr_type) + return thread_info.dereference() + + +class LxThreadInfoFunc (gdb.Function): + """Calculate Linux thread_info from task variable. + +$lx_thread_info(TASK): Given TASK, return the corresponding thread_info +variable.""" + + def __init__(self): + super(LxThreadInfoFunc, self).__init__("lx_thread_info") + + def invoke(self, task): + return get_thread_info(task) + + +LxThreadInfoFunc() -- cgit v0.10.2 From a4d86792c78d23257ab8ddd29ca16ce597361403 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:18 -0800 Subject: scripts/gdb: add get_gdbserver_type helper This helper probes the type of the gdb server. Supported are QEMU and KGDB so far. Knowledge about the gdb server is required e.g. to retrieve the current CPU or current task. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py index 71ee48c..a4a1640 100644 --- a/scripts/gdb/linux/utils.py +++ b/scripts/gdb/linux/utils.py @@ -119,3 +119,38 @@ def is_target_arch(arch): if target_arch is None: target_arch = gdb.execute("show architecture", to_string=True) return arch in target_arch + + +GDBSERVER_QEMU = 0 +GDBSERVER_KGDB = 1 +gdbserver_type = None + + +def get_gdbserver_type(): + def exit_handler(event): + global gdbserver_type + gdbserver_type = None + gdb.events.exited.disconnect(exit_handler) + + def probe_qemu(): + try: + return gdb.execute("monitor info version", to_string=True) != "" + except: + return False + + def probe_kgdb(): + try: + thread_info = gdb.execute("info thread 2", to_string=True) + return "shadowCPU0" in thread_info + except: + return False + + global gdbserver_type + if gdbserver_type is None: + if probe_qemu(): + gdbserver_type = GDBSERVER_QEMU + elif probe_kgdb(): + gdbserver_type = GDBSERVER_KGDB + if not gdbserver_type is None and hasattr(gdb, 'events'): + gdb.events.exited.connect(exit_handler) + return gdbserver_type -- cgit v0.10.2 From fe7f9ed98dad611ceaf17403f1c5bfd016eadcaa Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:21 -0800 Subject: scripts/gdb: add internal helper and convenience function for per-cpu lookup This function allows to obtain a per-cpu variable, either of the current or an explicitly specified CPU. Note: sparc64 version is untested. Signed-off-by: Jan Kiszka Cc: "David S. Miller" Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py new file mode 100644 index 0000000..18337e0 --- /dev/null +++ b/scripts/gdb/linux/cpus.py @@ -0,0 +1,68 @@ +# +# gdb helper commands and functions for Linux kernel debugging +# +# per-cpu tools +# +# Copyright (c) Siemens AG, 2011-2013 +# +# Authors: +# Jan Kiszka +# +# This work is licensed under the terms of the GNU GPL version 2. +# + +import gdb + +from linux import tasks, utils + + +MAX_CPUS = 4096 + + +def get_current_cpu(): + if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU: + return gdb.selected_thread().num - 1 + elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB: + tid = gdb.selected_thread().ptid[2] + if tid > (0x100000000 - MAX_CPUS - 2): + return 0x100000000 - tid - 2 + else: + return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu'] + else: + raise gdb.GdbError("Sorry, obtaining the current CPU is not yet " + "supported with this gdb server.") + + +def per_cpu(var_ptr, cpu): + if cpu == -1: + cpu = get_current_cpu() + if utils.is_target_arch("sparc:v9"): + offset = gdb.parse_and_eval( + "trap_block[{0}].__per_cpu_base".format(str(cpu))) + else: + try: + offset = gdb.parse_and_eval( + "__per_cpu_offset[{0}]".format(str(cpu))) + except gdb.error: + # !CONFIG_SMP case + offset = 0 + pointer = var_ptr.cast(utils.get_long_type()) + offset + return pointer.cast(var_ptr.type).dereference() + + +class PerCpu(gdb.Function): + """Return per-cpu variable. + +$lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the +given CPU number. If CPU is omitted, the CPU of the current context is used. +Note that VAR has to be quoted as string.""" + + def __init__(self): + super(PerCpu, self).__init__("lx_per_cpu") + + def invoke(self, var_name, cpu=-1): + var_ptr = gdb.parse_and_eval("&" + var_name.string()) + return per_cpu(var_ptr, cpu) + + +PerCpu() diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py index 4d7eb2c..4848928 100644 --- a/scripts/gdb/vmlinux-gdb.py +++ b/scripts/gdb/vmlinux-gdb.py @@ -27,3 +27,4 @@ else: import linux.modules import linux.dmesg import linux.tasks + import linux.cpus -- cgit v0.10.2 From 116b47b4da037547585cebe4e3275ef68905d509 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:24 -0800 Subject: scripts/gdb: add lx_current convenience function This is a shorthand for *$lx_per_cpu("current_task"), i.e. a convenience function to retrieve the currently running task of the active context. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py index 18337e0..b683da9 100644 --- a/scripts/gdb/linux/cpus.py +++ b/scripts/gdb/linux/cpus.py @@ -66,3 +66,20 @@ Note that VAR has to be quoted as string.""" PerCpu() + + +class LxCurrentFunc(gdb.Function): + """Return current task. + +$lx_current([CPU]): Return the per-cpu task variable for the given CPU +number. If CPU is omitted, the CPU of the current context is used.""" + + def __init__(self): + super(LxCurrentFunc, self).__init__("lx_current") + + def invoke(self, cpu=-1): + var_ptr = gdb.parse_and_eval("¤t_task") + return per_cpu(var_ptr, cpu).dereference() + + +LxCurrentFunc() -- cgit v0.10.2 From 3d4cd9c94191f60cbb741cfbaa770d442c4680aa Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:27 -0800 Subject: scripts/gdb: add class to iterate over CPU masks Will be used first to count module references. It is optimized to read the mask only once per stop. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py index b683da9..c1441f2 100644 --- a/scripts/gdb/linux/cpus.py +++ b/scripts/gdb/linux/cpus.py @@ -50,6 +50,60 @@ def per_cpu(var_ptr, cpu): return pointer.cast(var_ptr.type).dereference() +cpu_mask = {} + + +def cpu_mask_invalidate(event): + global cpu_mask + cpu_mask = {} + gdb.events.stop.disconnect(cpu_mask_invalidate) + if hasattr(gdb.events, 'new_objfile'): + gdb.events.new_objfile.disconnect(cpu_mask_invalidate) + + +class CpuList(): + def __init__(self, mask_name): + global cpu_mask + self.mask = None + if mask_name in cpu_mask: + self.mask = cpu_mask[mask_name] + if self.mask is None: + self.mask = gdb.parse_and_eval(mask_name + ".bits") + if hasattr(gdb, 'events'): + cpu_mask[mask_name] = self.mask + gdb.events.stop.connect(cpu_mask_invalidate) + if hasattr(gdb.events, 'new_objfile'): + gdb.events.new_objfile.connect(cpu_mask_invalidate) + self.bits_per_entry = self.mask[0].type.sizeof * 8 + self.num_entries = self.mask.type.sizeof * 8 / self.bits_per_entry + self.entry = -1 + self.bits = 0 + + def __iter__(self): + return self + + def next(self): + while self.bits == 0: + self.entry += 1 + if self.entry == self.num_entries: + raise StopIteration + self.bits = self.mask[self.entry] + if self.bits != 0: + self.bit = 0 + break + + while self.bits & 1 == 0: + self.bits >>= 1 + self.bit += 1 + + cpu = self.entry * self.bits_per_entry + self.bit + + self.bits >>= 1 + self.bit += 1 + + return cpu + + class PerCpu(gdb.Function): """Return per-cpu variable. -- cgit v0.10.2 From 5403727f985ba39967c899a56fff5bbd2c9a9f36 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:29 -0800 Subject: scripts/gdb: add lx-lsmod command This adds a lsmod-like command to list all currently loaded modules of the target. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py index 531f763..e7c99e9 100644 --- a/scripts/gdb/linux/modules.py +++ b/scripts/gdb/linux/modules.py @@ -13,7 +13,7 @@ import gdb -from linux import utils +from linux import cpus, utils module_type = utils.CachedType("struct module") @@ -65,3 +65,47 @@ of the target and return that module variable which MODULE matches.""" LxModule() + + +class LxLsmod(gdb.Command): + """List currently loaded modules.""" + + _module_use_type = utils.CachedType("struct module_use") + + def __init__(self): + super(LxLsmod, self).__init__("lx-lsmod", gdb.COMMAND_DATA) + + def invoke(self, arg, from_tty): + gdb.write( + "Address{0} Module Size Used by\n".format( + " " if utils.get_long_type().sizeof == 8 else "")) + + for module in ModuleList(): + ref = 0 + module_refptr = module['refptr'] + for cpu in cpus.CpuList("cpu_possible_mask"): + refptr = cpus.per_cpu(module_refptr, cpu) + ref += refptr['incs'] + ref -= refptr['decs'] + + gdb.write("{address} {name:<19} {size:>8} {ref}".format( + address=str(module['module_core']).split()[0], + name=module['name'].string(), + size=module['core_size'], + ref=ref)) + + source_list = module['source_list'] + t = self._module_use_type.get_type().pointer() + entry = source_list['next'] + first = True + while entry != source_list.address: + use = utils.container_of(entry, t, "source_list") + gdb.write("{separator}{name}".format( + separator=" " if first else ",", + name=use['source']['name'].string())) + first = False + entry = entry['next'] + gdb.write("\n") + + +LxLsmod() -- cgit v0.10.2 From bda1a921670e60d4c9aafb50f0b7b4773db66256 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:32 -0800 Subject: scripts/gdb: add basic documentation Signed-off-by: Jan Kiszka Cc: Rob Landley Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/gdb-kernel-debugging.txt b/Documentation/gdb-kernel-debugging.txt new file mode 100644 index 0000000..7050ce8 --- /dev/null +++ b/Documentation/gdb-kernel-debugging.txt @@ -0,0 +1,160 @@ +Debugging kernel and modules via gdb +==================================== + +The kernel debugger kgdb, hypervisors like QEMU or JTAG-based hardware +interfaces allow to debug the Linux kernel and its modules during runtime +using gdb. Gdb comes with a powerful scripting interface for python. The +kernel provides a collection of helper scripts that can simplify typical +kernel debugging steps. This is a short tutorial about how to enable and use +them. It focuses on QEMU/KVM virtual machines as target, but the examples can +be transferred to the other gdb stubs as well. + + +Requirements +------------ + + o gdb 7.2+ (recommended: 7.4+) with python support enabled (typically true + for distributions) + + +Setup +----- + + o Create a virtual Linux machine for QEMU/KVM (see www.linux-kvm.org and + www.qemu.org for more details). For cross-development, + http://landley.net/aboriginal/bin keeps a pool of machine images and + toolchains that can be helpful to start from. + + o Build the kernel with CONFIG_GDB_SCRIPTS enabled, but leave + CONFIG_DEBUG_INFO_REDUCED off. If your architecture supports + CONFIG_FRAME_POINTER, keep it enabled. + + o Install that kernel on the guest. + + Alternatively, QEMU allows to boot the kernel directly using -kernel, + -append, -initrd command line switches. This is generally only useful if + you do not depend on modules. See QEMU documentation for more details on + this mode. + + o Enable the gdb stub of QEMU/KVM, either + - at VM startup time by appending "-s" to the QEMU command line + or + - during runtime by issuing "gdbserver" from the QEMU monitor + console + + o cd /path/to/linux-build + + o Start gdb: gdb vmlinux + + Note: Some distros may restrict auto-loading of gdb scripts to known safe + directories. In case gdb reports to refuse loading vmlinux-gdb.py, add + + add-auto-load-safe-path /path/to/linux-build + + to ~/.gdbinit. See gdb help for more details. + + o Attach to the booted guest: + (gdb) target remote :1234 + + +Examples of using the Linux-provided gdb helpers +------------------------------------------------ + + o Load module (and main kernel) symbols: + (gdb) lx-symbols + loading vmlinux + scanning for modules in /home/user/linux/build + loading @0xffffffffa0020000: /home/user/linux/build/net/netfilter/xt_tcpudp.ko + loading @0xffffffffa0016000: /home/user/linux/build/net/netfilter/xt_pkttype.ko + loading @0xffffffffa0002000: /home/user/linux/build/net/netfilter/xt_limit.ko + loading @0xffffffffa00ca000: /home/user/linux/build/net/packet/af_packet.ko + loading @0xffffffffa003c000: /home/user/linux/build/fs/fuse/fuse.ko + ... + loading @0xffffffffa0000000: /home/user/linux/build/drivers/ata/ata_generic.ko + + o Set a breakpoint on some not yet loaded module function, e.g.: + (gdb) b btrfs_init_sysfs + Function "btrfs_init_sysfs" not defined. + Make breakpoint pending on future shared library load? (y or [n]) y + Breakpoint 1 (btrfs_init_sysfs) pending. + + o Continue the target + (gdb) c + + o Load the module on the target and watch the symbols being loaded as well as + the breakpoint hit: + loading @0xffffffffa0034000: /home/user/linux/build/lib/libcrc32c.ko + loading @0xffffffffa0050000: /home/user/linux/build/lib/lzo/lzo_compress.ko + loading @0xffffffffa006e000: /home/user/linux/build/lib/zlib_deflate/zlib_deflate.ko + loading @0xffffffffa01b1000: /home/user/linux/build/fs/btrfs/btrfs.ko + + Breakpoint 1, btrfs_init_sysfs () at /home/user/linux/fs/btrfs/sysfs.c:36 + 36 btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); + + o Dump the log buffer of the target kernel: + (gdb) lx-dmesg + [ 0.000000] Initializing cgroup subsys cpuset + [ 0.000000] Initializing cgroup subsys cpu + [ 0.000000] Linux version 3.8.0-rc4-dbg+ (... + [ 0.000000] Command line: root=/dev/sda2 resume=/dev/sda1 vga=0x314 + [ 0.000000] e820: BIOS-provided physical RAM map: + [ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable + [ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved + .... + + o Examine fields of the current task struct: + (gdb) p $lx_current().pid + $1 = 4998 + (gdb) p $lx_current().comm + $2 = "modprobe\000\000\000\000\000\000\000" + + o Make use of the per-cpu function for the current or a specified CPU: + (gdb) p $lx_per_cpu("runqueues").nr_running + $3 = 1 + (gdb) p $lx_per_cpu("runqueues", 2).nr_running + $4 = 0 + + o Dig into hrtimers using the container_of helper: + (gdb) set $next = $lx_per_cpu("hrtimer_bases").clock_base[0].active.next + (gdb) p *$container_of($next, "struct hrtimer", "node") + $5 = { + node = { + node = { + __rb_parent_color = 18446612133355256072, + rb_right = 0x0 , + rb_left = 0x0 + }, + expires = { + tv64 = 1835268000000 + } + }, + _softexpires = { + tv64 = 1835268000000 + }, + function = 0xffffffff81078232 , + base = 0xffff88003fd0d6f0, + state = 1, + start_pid = 0, + start_site = 0xffffffff81055c1f , + start_comm = "swapper/2\000\000\000\000\000\000" + } + + +List of commands and functions +------------------------------ + +The number of commands and convenience functions may evolve over the time, +this is just a snapshot of the initial version: + + (gdb) apropos lx + function lx_current -- Return current task + function lx_module -- Find module by name and return the module variable + function lx_per_cpu -- Return per-cpu variable + function lx_task_by_pid -- Find Linux task by PID and return the task_struct variable + function lx_thread_info -- Calculate Linux thread_info from task variable + lx-dmesg -- Print Linux kernel log buffer + lx-lsmod -- List currently loaded modules + lx-symbols -- (Re-)load symbols of Linux kernel and currently loaded modules + +Detailed help can be obtained via "help " for commands and "help +function " for convenience functions. -- cgit v0.10.2 From 276d97d90a2485f9a830a7a8242e4317b24c896f Mon Sep 17 00:00:00 2001 From: Pantelis Koukousoulas Date: Tue, 17 Feb 2015 13:47:35 -0800 Subject: scripts/gdb: port to python3 / gdb7.7 I tried to use these scripts in an ubuntu 14.04 host (gdb 7.7 compiled against python 3.3) but there were several errors. I believe this patch fixes these issues so that the commands now work (I tested lx-symbols, lx-dmesg, lx-lsmod). Main issues that needed to be resolved: * In python 2 iterators have a "next()" method. In python 3 it is __next__() instead (so let's just add both). * In older python versions there was an implicit conversion in object.__format__() (used when an object is in string.format()) where it was converting the object to str first and then calling str's __format__(). This has now been removed so we must explicitly convert to str the objects for which we need to keep this behavior. * In dmesg.py: in python 3 log_buf is now a "memoryview" object which needs to be converted to a string in order to use string methods like "splitlines()". Luckily memoryview exists in python 2.7.6 as well, so we can convert log_buf to memoryview and use the same code in both python 2 and python 3. This version of the patch has now been tested with gdb 7.7 and both python 3.4 and python 2.7.6 (I think asking for at least python 2.7.6 is a reasonable requirement instead of complicating the code with version checks etc). Signed-off-by: Pantelis Koukousoulas Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py index c1441f2..8045871 100644 --- a/scripts/gdb/linux/cpus.py +++ b/scripts/gdb/linux/cpus.py @@ -82,7 +82,7 @@ class CpuList(): def __iter__(self): return self - def next(self): + def __next__(self): while self.bits == 0: self.entry += 1 if self.entry == self.num_entries: @@ -103,6 +103,9 @@ class CpuList(): return cpu + def next(self): + return self.__next__() + class PerCpu(gdb.Function): """Return per-cpu variable. diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py index 7650f24..3c947f0 100644 --- a/scripts/gdb/linux/dmesg.py +++ b/scripts/gdb/linux/dmesg.py @@ -51,9 +51,10 @@ class LxDmesg(gdb.Command): continue text_len = utils.read_u16(log_buf[pos + 10:pos + 12]) + text = log_buf[pos + 16:pos + 16 + text_len] time_stamp = utils.read_u64(log_buf[pos:pos + 8]) - for line in log_buf[pos + 16:pos + 16 + text_len].splitlines(): + for line in memoryview(text).tobytes().splitlines(): gdb.write("[{time:12.6f}] {line}\n".format( time=time_stamp / 1000000000.0, line=line)) diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py index e7c99e9..2dbf679 100644 --- a/scripts/gdb/linux/modules.py +++ b/scripts/gdb/linux/modules.py @@ -30,7 +30,7 @@ class ModuleList: def __iter__(self): return self - def next(self): + def __next__(self): entry = self.curr_entry if entry != self.end_of_list: self.curr_entry = entry['next'] @@ -38,6 +38,9 @@ class ModuleList: else: raise StopIteration + def next(self): + return self.__next__() + def find_module_by_name(name): for module in ModuleList(): @@ -91,8 +94,8 @@ class LxLsmod(gdb.Command): gdb.write("{address} {name:<19} {size:>8} {ref}".format( address=str(module['module_core']).split()[0], name=module['name'].string(), - size=module['core_size'], - ref=ref)) + size=str(module['core_size']), + ref=str(ref))) source_list = module['source_list'] t = self._module_use_type.get_type().pointer() diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py index 139841f..ae757fd 100644 --- a/scripts/gdb/linux/symbols.py +++ b/scripts/gdb/linux/symbols.py @@ -73,7 +73,7 @@ lx-symbols command.""" def _get_module_file(self, module_name): module_pattern = ".*/{0}\.ko$".format( - string.replace(module_name, "_", r"[_\-]")) + module_name.replace("_", r"[_\-]")) for name in self.module_files: if re.match(module_pattern, name) and os.path.exists(name): return name @@ -87,7 +87,7 @@ lx-symbols command.""" attrs = sect_attrs['attrs'] section_name_to_address = { attrs[n]['name'].string() : attrs[n]['address'] - for n in range(sect_attrs['nsections'])} + for n in range(int(sect_attrs['nsections']))} args = [] for section_name in [".data", ".data..read_mostly", ".rodata", ".bss"]: address = section_name_to_address.get(section_name) diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py index 63cd6c5..0008e75 100644 --- a/scripts/gdb/linux/tasks.py +++ b/scripts/gdb/linux/tasks.py @@ -30,7 +30,7 @@ class TaskList: def __iter__(self): return self - def next(self): + def __next__(self): t = self.curr_task if not t or t == self.curr_group: self.curr_group = \ @@ -45,6 +45,8 @@ class TaskList: self.task_ptr_type, "thread_group") return t + def next(self): + return self.__next__() def get_task_by_pid(pid): for task in TaskList(): diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py index a4a1640..128c306 100644 --- a/scripts/gdb/linux/utils.py +++ b/scripts/gdb/linux/utils.py @@ -83,7 +83,7 @@ def get_target_endianness(): elif "big endian" in endian: target_endianness = BIG_ENDIAN else: - raise gdb.GdgError("unknown endianness '{0}'".format(endian)) + raise gdb.GdgError("unknown endianness '{0}'".format(str(endian))) return target_endianness -- cgit v0.10.2 From 2478a8a15ccaddd68e84bb8791cd468f636673e9 Mon Sep 17 00:00:00 2001 From: Daniel Thompson Date: Tue, 17 Feb 2015 13:47:38 -0800 Subject: scripts/gdb: ignore byte-compiled python files Using the gdb scripts leaves byte-compiled python files in the scripts/ directory. These should be ignored by git. [jan.kiszka@siemens.com: drop redundant mrproper rule as suggested by Michal] Signed-off-by: Daniel Thompson Signed-off-by: Jan Kiszka Cc: Michal Marek Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/.gitignore b/.gitignore index 9ac9106..acb6afe 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ Module.symvers /TAGS /linux /vmlinux +/vmlinux-gdb.py /vmlinuz /System.map /Module.markers diff --git a/scripts/gdb/linux/.gitignore b/scripts/gdb/linux/.gitignore new file mode 100644 index 0000000..52e4e61 --- /dev/null +++ b/scripts/gdb/linux/.gitignore @@ -0,0 +1,2 @@ +*.pyc +*.pyo -- cgit v0.10.2 From 54e2289a34e13d956acb841a00c3a6f06aced3f9 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 17 Feb 2015 13:47:41 -0800 Subject: scripts/gdb: use a generator instead of iterator for task list The iterator does not return any task_struct from the thread_group list because the first condition in the 'if not t or ...' will only be the first time None. Instead of keeping track of the state ourself in the next() function, we fall back using Python's generator. Signed-off-by: Daniel Wagner Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py index 0008e75..e2037d9 100644 --- a/scripts/gdb/linux/tasks.py +++ b/scripts/gdb/linux/tasks.py @@ -18,38 +18,28 @@ from linux import utils task_type = utils.CachedType("struct task_struct") - -class TaskList: - def __init__(self): - global task_type - self.task_ptr_type = task_type.get_type().pointer() - self.init_task = gdb.parse_and_eval("init_task") - self.curr_group = self.init_task.address - self.curr_task = None - - def __iter__(self): - return self - - def __next__(self): - t = self.curr_task - if not t or t == self.curr_group: - self.curr_group = \ - utils.container_of(self.curr_group['tasks']['next'], - self.task_ptr_type, "tasks") - if self.curr_group == self.init_task.address: - raise StopIteration - t = self.curr_task = self.curr_group - else: - self.curr_task = \ - utils.container_of(t['thread_group']['next'], - self.task_ptr_type, "thread_group") - return t - - def next(self): - return self.__next__() +def task_lists(): + global task_type + task_ptr_type = task_type.get_type().pointer() + init_task = gdb.parse_and_eval("init_task").address + t = g = init_task + + while True: + while True: + yield t + + t = utils.container_of(t['thread_group']['next'], + task_ptr_type, "thread_group") + if t == g: + break + + t = g = utils.container_of(g['tasks']['next'], + task_ptr_type, "tasks") + if t == init_task: + return def get_task_by_pid(pid): - for task in TaskList(): + for task in task_lists(): if int(task['pid']) == pid: return task return None -- cgit v0.10.2 From fffb944c4e6d3882a7a15c494bd4cde36c68c39c Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:44 -0800 Subject: scripts/gdb: convert ModuleList to generator function Analogously to the task list, convert the module list to a generator function. It noticeably simplifies the code. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py index 2dbf679..6d49722 100644 --- a/scripts/gdb/linux/modules.py +++ b/scripts/gdb/linux/modules.py @@ -19,31 +19,20 @@ from linux import cpus, utils module_type = utils.CachedType("struct module") -class ModuleList: - def __init__(self): - global module_type - self.module_ptr_type = module_type.get_type().pointer() - modules = gdb.parse_and_eval("modules") - self.curr_entry = modules['next'] - self.end_of_list = modules.address - - def __iter__(self): - return self - - def __next__(self): - entry = self.curr_entry - if entry != self.end_of_list: - self.curr_entry = entry['next'] - return utils.container_of(entry, self.module_ptr_type, "list") - else: - raise StopIteration +def module_list(): + global module_type + module_ptr_type = module_type.get_type().pointer() + modules = gdb.parse_and_eval("modules") + entry = modules['next'] + end_of_list = modules.address - def next(self): - return self.__next__() + while entry != end_of_list: + yield utils.container_of(entry, module_ptr_type, "list") + entry = entry['next'] def find_module_by_name(name): - for module in ModuleList(): + for module in module_list(): if module['name'].string() == name: return module return None @@ -83,7 +72,7 @@ class LxLsmod(gdb.Command): "Address{0} Module Size Used by\n".format( " " if utils.get_long_type().sizeof == 8 else "")) - for module in ModuleList(): + for module in module_list(): ref = 0 module_refptr = module['refptr'] for cpu in cpus.CpuList("cpu_possible_mask"): diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py index ae757fd..bf05e45 100644 --- a/scripts/gdb/linux/symbols.py +++ b/scripts/gdb/linux/symbols.py @@ -133,7 +133,7 @@ lx-symbols command.""" gdb.execute("symbol-file vmlinux") self.loaded_modules = [] - module_list = modules.ModuleList() + module_list = modules.module_list() if not module_list: gdb.write("no modules found\n") else: -- cgit v0.10.2 From a77e15e8b4ccaf43b3a527cbb882bf816c5a629d Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:47 -0800 Subject: scripts/gdb: convert CpuList to generator function Yet another code simplification. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py index 8045871..4297b83 100644 --- a/scripts/gdb/linux/cpus.py +++ b/scripts/gdb/linux/cpus.py @@ -61,50 +61,43 @@ def cpu_mask_invalidate(event): gdb.events.new_objfile.disconnect(cpu_mask_invalidate) -class CpuList(): - def __init__(self, mask_name): - global cpu_mask - self.mask = None - if mask_name in cpu_mask: - self.mask = cpu_mask[mask_name] - if self.mask is None: - self.mask = gdb.parse_and_eval(mask_name + ".bits") - if hasattr(gdb, 'events'): - cpu_mask[mask_name] = self.mask - gdb.events.stop.connect(cpu_mask_invalidate) - if hasattr(gdb.events, 'new_objfile'): - gdb.events.new_objfile.connect(cpu_mask_invalidate) - self.bits_per_entry = self.mask[0].type.sizeof * 8 - self.num_entries = self.mask.type.sizeof * 8 / self.bits_per_entry - self.entry = -1 - self.bits = 0 - - def __iter__(self): - return self - - def __next__(self): - while self.bits == 0: - self.entry += 1 - if self.entry == self.num_entries: - raise StopIteration - self.bits = self.mask[self.entry] - if self.bits != 0: - self.bit = 0 +def cpu_list(mask_name): + global cpu_mask + mask = None + if mask_name in cpu_mask: + mask = cpu_mask[mask_name] + if mask is None: + mask = gdb.parse_and_eval(mask_name + ".bits") + if hasattr(gdb, 'events'): + cpu_mask[mask_name] = mask + gdb.events.stop.connect(cpu_mask_invalidate) + if hasattr(gdb.events, 'new_objfile'): + gdb.events.new_objfile.connect(cpu_mask_invalidate) + bits_per_entry = mask[0].type.sizeof * 8 + num_entries = mask.type.sizeof * 8 / bits_per_entry + entry = -1 + bits = 0 + + while True: + while bits == 0: + entry += 1 + if entry == num_entries: + return + bits = mask[entry] + if bits != 0: + bit = 0 break - while self.bits & 1 == 0: - self.bits >>= 1 - self.bit += 1 - - cpu = self.entry * self.bits_per_entry + self.bit + while bits & 1 == 0: + bits >>= 1 + bit += 1 - self.bits >>= 1 - self.bit += 1 + cpu = entry * bits_per_entry + bit - return cpu + bits >>= 1 + bit += 1 - def next(self): - return self.__next__() + yield cpu class PerCpu(gdb.Function): diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py index 6d49722..a1504c4 100644 --- a/scripts/gdb/linux/modules.py +++ b/scripts/gdb/linux/modules.py @@ -75,7 +75,7 @@ class LxLsmod(gdb.Command): for module in module_list(): ref = 0 module_refptr = module['refptr'] - for cpu in cpus.CpuList("cpu_possible_mask"): + for cpu in cpus.cpu_list("cpu_possible_mask"): refptr = cpus.per_cpu(module_refptr, cpu) ref += refptr['incs'] ref -= refptr['decs'] -- cgit v0.10.2 From 158daf167377dfc49ce6d70f70fd7c6fab2df987 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:49 -0800 Subject: scripts/gdb: define maintainer I'm proposing myself for keeping an eye on these scripts and integrating contributions. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index 85024e2..a6c9b59 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4232,6 +4232,11 @@ W: http://www.icp-vortex.com/ S: Supported F: drivers/scsi/gdt* +GDB KERNEL DEBUGGING HELPER SCRIPTS +M: Jan Kiszka +S: Supported +F: scripts/gdb/ + GEMTEK FM RADIO RECEIVER DRIVER M: Hans Verkuil L: linux-media@vger.kernel.org -- cgit v0.10.2 From a9c5bcfa43420365535ef42c1ff1e83aa056f25e Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 17 Feb 2015 13:47:52 -0800 Subject: scripts/gdb: disable pagination while printing from breakpoint handler While reporting the (refreshed) list of modules on automatic updates we may hit the page boundary of the output console and cause a stop if pagination is enabled. However, gdb does not accept user input while running over the breakpoint handler. So we get stuck, and the user is forced to interrupt gdb. Resolve this by disabling pagination during automatic symbol updates. We restore the user's configuration once done. Signed-off-by: Jan Kiszka Cc: Thomas Gleixner Cc: Jason Wessel Cc: Andi Kleen Cc: Ben Widawsky Cc: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py index bf05e45..cd5bea9 100644 --- a/scripts/gdb/linux/symbols.py +++ b/scripts/gdb/linux/symbols.py @@ -34,12 +34,23 @@ if hasattr(gdb, 'Breakpoint'): # enforce update if object file is not found cmd.module_files_updated = False + # Disable pagination while reporting symbol (re-)loading. + # The console input is blocked in this context so that we would + # get stuck waiting for the user to acknowledge paged output. + show_pagination = gdb.execute("show pagination", to_string=True) + pagination = show_pagination.endswith("on.\n") + gdb.execute("set pagination off") + if module_name in cmd.loaded_modules: gdb.write("refreshing all symbols to reload module " "'{0}'\n".format(module_name)) cmd.load_all_symbols() else: cmd.load_module_symbols(module) + + # restore pagination state + gdb.execute("set pagination %s" % ("on" if pagination else "off")) + return False -- cgit v0.10.2 From 52644c9ab3faefbfbf07a19c24c4e74e33cfd796 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Tue, 17 Feb 2015 13:47:55 -0800 Subject: ipc,sem: use current->state helpers Call __set_current_state() instead of assigning the new state directly. These interfaces also aid CONFIG_DEBUG_ATOMIC_SLEEP environments, keeping track of who changed the state. Signed-off-by: Davidlohr Bueso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/ipc/sem.c b/ipc/sem.c index 6115146..9284211 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1941,7 +1941,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, queue.sleeper = current; sleep_again: - current->state = TASK_INTERRUPTIBLE; + __set_current_state(TASK_INTERRUPTIBLE); sem_unlock(sma, locknum); rcu_read_unlock(); -- cgit v0.10.2 From 3a9af0bd34410a255d27024ea1bc28dc4e3a0044 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 17 Feb 2015 13:47:58 -0800 Subject: samples/seccomp: improve label helper Fixes a potential corruption with uninitialized stack memory in the seccomp BPF sample program. [akpm@linux-foundation.org: coding-style fixlet] Signed-off-by: Kees Cook Reported-by: Robert Swiecki Tested-by: Robert Swiecki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/samples/seccomp/bpf-fancy.c b/samples/seccomp/bpf-fancy.c index 8eb483aa..e8b24f4 100644 --- a/samples/seccomp/bpf-fancy.c +++ b/samples/seccomp/bpf-fancy.c @@ -25,7 +25,9 @@ int main(int argc, char **argv) { - struct bpf_labels l; + struct bpf_labels l = { + .count = 0, + }; static const char msg1[] = "Please type something: "; static const char msg2[] = "You typed: "; char buf[256]; diff --git a/samples/seccomp/bpf-helper.c b/samples/seccomp/bpf-helper.c index 579cfe3..05cb4d5 100644 --- a/samples/seccomp/bpf-helper.c +++ b/samples/seccomp/bpf-helper.c @@ -10,6 +10,7 @@ */ #include +#include #include #include "bpf-helper.h" @@ -63,6 +64,11 @@ __u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label) { struct __bpf_label *begin = labels->labels, *end; int id; + + if (labels->count == BPF_LABELS_MAX) { + fprintf(stderr, "Too many labels\n"); + exit(1); + } if (labels->count == 0) { begin->label = label; begin->location = 0xffffffff; -- cgit v0.10.2 From 580c57f1076872ebc2427f898b927944ce170f2d Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 17 Feb 2015 13:48:00 -0800 Subject: seccomp: cap SECCOMP_RET_ERRNO data to MAX_ERRNO The value resulting from the SECCOMP_RET_DATA mask could exceed MAX_ERRNO when setting errno during a SECCOMP_RET_ERRNO filter action. This makes sure we have a reliable value being set, so that an invalid errno will not be ignored by userspace. Signed-off-by: Kees Cook Reported-by: Dmitry V. Levin Cc: Andy Lutomirski Cc: Will Drewry Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 4ef9687..4f44028 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -629,7 +629,9 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) switch (action) { case SECCOMP_RET_ERRNO: - /* Set the low-order 16-bits as a errno. */ + /* Set low-order bits as an errno, capped at MAX_ERRNO. */ + if (data > MAX_ERRNO) + data = MAX_ERRNO; syscall_set_return_value(current, task_pt_regs(current), -data, 0); goto skip; -- cgit v0.10.2