Skip to content

Commit

Permalink
Merge remote-tracking branch 'efi/urgent' into x86/urgent
Browse files Browse the repository at this point in the history
There have been reports of EFI crashes since -rc1. The following two
commits fix known issues.

 * Fix boot failure on 32-bit EFI due to the recent EFI memmap changes
   merged during the merge window - Borislav Petkov

 * Avoid a crash during efi_bgrt_init() by detecting invalid BGRT
   headers based on the 'status' field.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
  • Loading branch information
H. Peter Anvin committed Feb 14, 2014
2 parents 4640c7e + 0950337 commit 31fce91
Show file tree
Hide file tree
Showing 34 changed files with 215 additions and 107 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
VERSION = 3
PATCHLEVEL = 14
SUBLEVEL = 0
EXTRAVERSION = -rc1
EXTRAVERSION = -rc2
NAME = Shuffling Zombie Juror

# *DOCUMENTATION*
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/include/asm/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ extern void __init efi_map_region_fixed(efi_memory_desc_t *md);
extern void efi_sync_low_kernel_mappings(void);
extern void efi_setup_page_tables(void);
extern void __init old_map_region(efi_memory_desc_t *md);
extern void __init runtime_code_page_mkexec(void);
extern void __init efi_runtime_mkexec(void);

struct efi_setup_data {
u64 fw_vendor;
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/platform/efi/efi-bgrt.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ void __init efi_bgrt_init(void)

if (bgrt_tab->header.length < sizeof(*bgrt_tab))
return;
if (bgrt_tab->version != 1)
if (bgrt_tab->version != 1 || bgrt_tab->status != 1)
return;
if (bgrt_tab->image_type != 0 || !bgrt_tab->image_address)
return;
Expand Down
5 changes: 2 additions & 3 deletions arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
set_memory_nx(addr, npages);
}

static void __init runtime_code_page_mkexec(void)
void __init runtime_code_page_mkexec(void)
{
efi_memory_desc_t *md;
void *p;
Expand Down Expand Up @@ -1069,8 +1069,7 @@ void __init efi_enter_virtual_mode(void)
efi.update_capsule = virt_efi_update_capsule;
efi.query_capsule_caps = virt_efi_query_capsule_caps;

if (efi_enabled(EFI_OLD_MEMMAP) && (__supported_pte_mask & _PAGE_NX))
runtime_code_page_mkexec();
efi_runtime_mkexec();

kfree(new_memmap);

Expand Down
6 changes: 6 additions & 0 deletions arch/x86/platform/efi/efi_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,9 @@ void efi_call_phys_epilog(void)

local_irq_restore(efi_rt_eflags);
}

void __init efi_runtime_mkexec(void)
{
if (__supported_pte_mask & _PAGE_NX)
runtime_code_page_mkexec();
}
9 changes: 9 additions & 0 deletions arch/x86/platform/efi/efi_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,12 @@ void __init parse_efi_setup(u64 phys_addr, u32 data_len)
{
efi_setup = phys_addr + sizeof(struct setup_data);
}

void __init efi_runtime_mkexec(void)
{
if (!efi_enabled(EFI_OLD_MEMMAP))
return;

if (__supported_pte_mask & _PAGE_NX)
runtime_code_page_mkexec();
}
9 changes: 3 additions & 6 deletions drivers/char/virtio_console.c
Original file line number Diff line number Diff line change
Expand Up @@ -890,22 +890,19 @@ static int pipe_to_sg(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
} else {
/* Failback to copying a page */
struct page *page = alloc_page(GFP_KERNEL);
char *src = buf->ops->map(pipe, buf, 1);
char *dst;
char *src;

if (!page)
return -ENOMEM;
dst = kmap(page);

offset = sd->pos & ~PAGE_MASK;

len = sd->len;
if (len + offset > PAGE_SIZE)
len = PAGE_SIZE - offset;

memcpy(dst + offset, src + buf->offset, len);

kunmap(page);
src = buf->ops->map(pipe, buf, 1);
memcpy(page_address(page) + offset, src + buf->offset, len);
buf->ops->unmap(pipe, buf, src);

sg_set_page(&(sgl->sg[sgl->n]), page, len, offset);
Expand Down
2 changes: 2 additions & 0 deletions fs/btrfs/compression.c
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,8 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
bytes = min(bytes, working_bytes);
kaddr = kmap_atomic(page_out);
memcpy(kaddr + *pg_offset, buf + buf_offset, bytes);
if (*pg_index == (vcnt - 1) && *pg_offset == 0)
memset(kaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
kunmap_atomic(kaddr);
flush_dcache_page(page_out);

Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -2385,6 +2385,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
spin_unlock(&delayed_refs->lock);
locked_ref = NULL;
cond_resched();
count++;
continue;
}

Expand Down
6 changes: 3 additions & 3 deletions fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -4525,7 +4525,7 @@ static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg)
spin_lock(&root->fs_info->super_lock);
strcpy(super_block->label, label);
spin_unlock(&root->fs_info->super_lock);
ret = btrfs_end_transaction(trans, root);
ret = btrfs_commit_transaction(trans, root);

out_unlock:
mnt_drop_write_file(file);
Expand Down Expand Up @@ -4668,7 +4668,7 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg)
if (ret)
return ret;

trans = btrfs_start_transaction(root, 1);
trans = btrfs_start_transaction(root, 0);
if (IS_ERR(trans))
return PTR_ERR(trans);

Expand All @@ -4689,7 +4689,7 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg)
btrfs_set_super_incompat_flags(super_block, newflags);
spin_unlock(&root->fs_info->super_lock);

return btrfs_end_transaction(trans, root);
return btrfs_commit_transaction(trans, root);
}

long btrfs_ioctl(struct file *file, unsigned int
Expand Down
8 changes: 3 additions & 5 deletions fs/btrfs/send.c
Original file line number Diff line number Diff line change
Expand Up @@ -2774,8 +2774,6 @@ static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino)
return 0;
}

#ifdef CONFIG_BTRFS_ASSERT

static int del_waiting_dir_move(struct send_ctx *sctx, u64 ino)
{
struct rb_node *n = sctx->waiting_dir_moves.rb_node;
Expand All @@ -2796,8 +2794,6 @@ static int del_waiting_dir_move(struct send_ctx *sctx, u64 ino)
return -ENOENT;
}

#endif

static int add_pending_dir_move(struct send_ctx *sctx, u64 parent_ino)
{
struct rb_node **p = &sctx->pending_dir_moves.rb_node;
Expand Down Expand Up @@ -2902,7 +2898,9 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
}

sctx->send_progress = sctx->cur_ino + 1;
ASSERT(del_waiting_dir_move(sctx, pm->ino) == 0);
ret = del_waiting_dir_move(sctx, pm->ino);
ASSERT(ret == 0);

ret = get_cur_path(sctx, pm->ino, pm->gen, to_path);
if (ret < 0)
goto out;
Expand Down
4 changes: 2 additions & 2 deletions fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -2559,8 +2559,8 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov,
if (rc > 0) {
ssize_t err;

err = generic_write_sync(file, pos, rc);
if (err < 0 && rc > 0)
err = generic_write_sync(file, iocb->ki_pos - rc, rc);
if (err < 0)
rc = err;
}

Expand Down
2 changes: 1 addition & 1 deletion fs/ext4/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
if (ret > 0) {
ssize_t err;

err = generic_write_sync(file, pos, ret);
err = generic_write_sync(file, iocb->ki_pos - ret, ret);
if (err < 0 && ret > 0)
ret = err;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/ntfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -2134,7 +2134,7 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
ret = ntfs_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos);
mutex_unlock(&inode->i_mutex);
if (ret > 0) {
int err = generic_write_sync(file, pos, ret);
int err = generic_write_sync(file, iocb->ki_pos - ret, ret);
if (err < 0)
ret = err;
}
Expand Down
17 changes: 0 additions & 17 deletions fs/sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,23 +222,6 @@ SYSCALL_DEFINE1(fdatasync, unsigned int, fd)
return do_fsync(fd, 1);
}

/**
* generic_write_sync - perform syncing after a write if file / inode is sync
* @file: file to which the write happened
* @pos: offset where the write started
* @count: length of the write
*
* This is just a simple wrapper about our general syncing function.
*/
int generic_write_sync(struct file *file, loff_t pos, loff_t count)
{
if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host))
return 0;
return vfs_fsync_range(file, pos, pos + count - 1,
(file->f_flags & __O_SYNC) ? 0 : 1);
}
EXPORT_SYMBOL(generic_write_sync);

/*
* sys_sync_file_range() permits finely controlled syncing over a segment of
* a file in the range offset .. (offset+nbytes-1) inclusive. If nbytes is
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/xfs_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ xfs_file_aio_write(
XFS_STATS_ADD(xs_write_bytes, ret);

/* Handle various SYNC-type writes */
err = generic_write_sync(file, pos, ret);
err = generic_write_sync(file, iocb->ki_pos - ret, ret);
if (err < 0)
ret = err;
}
Expand Down
8 changes: 7 additions & 1 deletion include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2274,7 +2274,13 @@ extern int filemap_fdatawrite_range(struct address_space *mapping,
extern int vfs_fsync_range(struct file *file, loff_t start, loff_t end,
int datasync);
extern int vfs_fsync(struct file *file, int datasync);
extern int generic_write_sync(struct file *file, loff_t pos, loff_t count);
static inline int generic_write_sync(struct file *file, loff_t pos, loff_t count)
{
if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host))
return 0;
return vfs_fsync_range(file, pos, pos + count - 1,
(file->f_flags & __O_SYNC) ? 0 : 1);
}
extern void emergency_sync(void);
extern void emergency_remount(void);
#ifdef CONFIG_BLOCK
Expand Down
4 changes: 2 additions & 2 deletions mm/filemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2553,8 +2553,8 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
if (ret > 0) {
ssize_t err;

err = generic_write_sync(file, pos, ret);
if (err < 0 && ret > 0)
err = generic_write_sync(file, iocb->ki_pos - ret, ret);
if (err < 0)
ret = err;
}
return ret;
Expand Down
2 changes: 2 additions & 0 deletions security/selinux/nlmsgtab.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/inet_diag.h>
#include <linux/xfrm.h>
#include <linux/audit.h>
#include <linux/sock_diag.h>

#include "flask.h"
#include "av_permissions.h"
Expand Down Expand Up @@ -78,6 +79,7 @@ static struct nlmsg_perm nlmsg_tcpdiag_perms[] =
{
{ TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
{ DCCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
{ SOCK_DIAG_BY_FAMILY, NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
};

static struct nlmsg_perm nlmsg_xfrm_perms[] =
Expand Down
4 changes: 4 additions & 0 deletions security/selinux/ss/services.c
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,10 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
struct context context;
int rc = 0;

/* An empty security context is never valid. */
if (!scontext_len)
return -EINVAL;

if (!ss_initialized) {
int i;

Expand Down
33 changes: 29 additions & 4 deletions tools/perf/builtin-buildid-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,35 @@ static int build_id_cache__kcore_dir(char *dir, size_t sz)
return 0;
}

static bool same_kallsyms_reloc(const char *from_dir, char *to_dir)
{
char from[PATH_MAX];
char to[PATH_MAX];
const char *name;
u64 addr1 = 0, addr2 = 0;
int i;

scnprintf(from, sizeof(from), "%s/kallsyms", from_dir);
scnprintf(to, sizeof(to), "%s/kallsyms", to_dir);

for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
addr1 = kallsyms__get_function_start(from, name);
if (addr1)
break;
}

if (name)
addr2 = kallsyms__get_function_start(to, name);

return addr1 == addr2;
}

static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
size_t to_dir_sz)
{
char from[PATH_MAX];
char to[PATH_MAX];
char to_subdir[PATH_MAX];
struct dirent *dent;
int ret = -1;
DIR *d;
Expand All @@ -86,10 +110,11 @@ static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
continue;
scnprintf(to, sizeof(to), "%s/%s/modules", to_dir,
dent->d_name);
if (!compare_proc_modules(from, to)) {
scnprintf(to, sizeof(to), "%s/%s", to_dir,
dent->d_name);
strlcpy(to_dir, to, to_dir_sz);
scnprintf(to_subdir, sizeof(to_subdir), "%s/%s",
to_dir, dent->d_name);
if (!compare_proc_modules(from, to) &&
same_kallsyms_reloc(from_dir, to_subdir)) {
strlcpy(to_dir, to_subdir, to_dir_sz);
ret = 0;
break;
}
Expand Down
10 changes: 2 additions & 8 deletions tools/perf/builtin-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,7 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
* have no _text sometimes.
*/
err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
machine, "_text");
if (err < 0)
err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
machine, "_stext");
machine);
if (err < 0)
pr_err("Couldn't record guest kernel [%d]'s reference"
" relocation symbol.\n", machine->pid);
Expand Down Expand Up @@ -457,10 +454,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
}

err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
machine, "_text");
if (err < 0)
err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
machine, "_stext");
machine);
if (err < 0)
pr_err("Couldn't record kernel reference relocation symbol\n"
"Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
Expand Down
1 change: 0 additions & 1 deletion tools/perf/design.txt
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,6 @@ So to start with, in order to add HAVE_PERF_EVENTS to your Kconfig, you
will need at least this:
- asm/perf_event.h - a basic stub will suffice at first
- support for atomic64 types (and associated helper functions)
- set_perf_event_pending() implemented

If your architecture does have hardware capabilities, you can override the
weak stub hw_perf_event_init() to register hardware counters.
Expand Down
4 changes: 2 additions & 2 deletions tools/perf/perf.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@

#ifdef __aarch64__
#define mb() asm volatile("dmb ish" ::: "memory")
#define wmb() asm volatile("dmb ishld" ::: "memory")
#define rmb() asm volatile("dmb ishst" ::: "memory")
#define wmb() asm volatile("dmb ishst" ::: "memory")
#define rmb() asm volatile("dmb ishld" ::: "memory")
#define cpu_relax() asm volatile("yield" ::: "memory")
#endif

Expand Down
Loading

0 comments on commit 31fce91

Please sign in to comment.