Skip to content

Commit

Permalink
Changes representative of linux-3.10.0-1160.41.1.el7.tar.xz
Browse files Browse the repository at this point in the history
  • Loading branch information
da-x committed Aug 16, 2021
1 parent 764032d commit 0ebba03
Show file tree
Hide file tree
Showing 24 changed files with 281 additions and 45 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ EXTRAVERSION =
NAME = Unicycling Gorilla
RHEL_MAJOR = 7
RHEL_MINOR = 9
RHEL_RELEASE = 1160.36.2
RHEL_RELEASE = 1160.41.1

#
# DRM backport version
Expand Down
13 changes: 13 additions & 0 deletions arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,19 @@ config SECCOMP

If unsure, say Y. Only embedded should say N here.

config PPC_RTAS_FILTER
bool "Enable filtering of RTAS syscalls"
default y
depends on PPC_RTAS
help
The RTAS syscall API has security issues that could be used to
compromise system integrity. This option enforces restrictions on the
RTAS calls and arguments passed by userspace programs to mitigate
these issues.

Say Y unless you know what you are doing and the filter is causing
problems for you.

endmenu

config ISA_DMA_API
Expand Down
153 changes: 153 additions & 0 deletions arch/powerpc/kernel/rtas.c
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,147 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
return NULL;
}

#ifdef CONFIG_PPC_RTAS_FILTER

/*
* The sys_rtas syscall, as originally designed, allows root to pass
* arbitrary physical addresses to RTAS calls. A number of RTAS calls
* can be abused to write to arbitrary memory and do other things that
* are potentially harmful to system integrity, and thus should only
* be used inside the kernel and not exposed to userspace.
*
* All known legitimate users of the sys_rtas syscall will only ever
* pass addresses that fall within the RMO buffer, and use a known
* subset of RTAS calls.
*
* Accordingly, we filter RTAS requests to check that the call is
* permitted, and that provided pointers fall within the RMO buffer.
* The rtas_filters list contains an entry for each permitted call,
* with the indexes of the parameters which are expected to contain
* addresses and sizes of buffers allocated inside the RMO buffer.
*/
struct rtas_filter {
const char *name;
int token;
/* Indexes into the args buffer, -1 if not used */
int buf_idx1;
int size_idx1;
int buf_idx2;
int size_idx2;

int fixed_size;
};

static struct rtas_filter rtas_filters[] = {
{ "ibm,activate-firmware", -1, -1, -1, -1, -1 },
{ "ibm,configure-connector", -1, 0, -1, 1, -1, 4096 }, /* Special cased */
{ "display-character", -1, -1, -1, -1, -1 },
{ "ibm,display-message", -1, 0, -1, -1, -1 },
{ "ibm,errinjct", -1, 2, -1, -1, -1, 1024 },
{ "ibm,close-errinjct", -1, -1, -1, -1, -1 },
{ "ibm,open-errinjct", -1, -1, -1, -1, -1 },
{ "ibm,get-config-addr-info2", -1, -1, -1, -1, -1 },
{ "ibm,get-dynamic-sensor-state", -1, 1, -1, -1, -1 },
{ "ibm,get-indices", -1, 2, 3, -1, -1 },
{ "get-power-level", -1, -1, -1, -1, -1 },
{ "get-sensor-state", -1, -1, -1, -1, -1 },
{ "ibm,get-system-parameter", -1, 1, 2, -1, -1 },
{ "get-time-of-day", -1, -1, -1, -1, -1 },
{ "ibm,get-vpd", -1, 0, -1, 1, 2 },
{ "ibm,lpar-perftools", -1, 2, 3, -1, -1 },
{ "ibm,platform-dump", -1, 4, 5, -1, -1 },
{ "ibm,read-slot-reset-state", -1, -1, -1, -1, -1 },
{ "ibm,scan-log-dump", -1, 0, 1, -1, -1 },
{ "ibm,set-dynamic-indicator", -1, 2, -1, -1, -1 },
{ "ibm,set-eeh-option", -1, -1, -1, -1, -1 },
{ "set-indicator", -1, -1, -1, -1, -1 },
{ "set-power-level", -1, -1, -1, -1, -1 },
{ "set-time-for-power-on", -1, -1, -1, -1, -1 },
{ "ibm,set-system-parameter", -1, 1, -1, -1, -1 },
{ "set-time-of-day", -1, -1, -1, -1, -1 },
{ "ibm,suspend-me", -1, -1, -1, -1, -1 },
{ "ibm,update-nodes", -1, 0, -1, -1, -1, 4096 },
{ "ibm,update-properties", -1, 0, -1, -1, -1, 4096 },
{ "ibm,physical-attestation", -1, 0, 1, -1, -1 },
};

static bool in_rmo_buf(u32 base, u32 end)
{
return base >= rtas_rmo_buf &&
base < (rtas_rmo_buf + RTAS_RMOBUF_MAX) &&
base <= end &&
end >= rtas_rmo_buf &&
end < (rtas_rmo_buf + RTAS_RMOBUF_MAX);
}

static bool block_rtas_call(int token, int nargs,
struct rtas_args *args)
{
int i;

for (i = 0; i < ARRAY_SIZE(rtas_filters); i++) {
struct rtas_filter *f = &rtas_filters[i];
u32 base, size, end;

if (token != f->token)
continue;

if (f->buf_idx1 != -1) {
base = be32_to_cpu(args->args[f->buf_idx1]);
if (f->size_idx1 != -1)
size = be32_to_cpu(args->args[f->size_idx1]);
else if (f->fixed_size)
size = f->fixed_size;
else
size = 1;

end = base + size - 1;
if (!in_rmo_buf(base, end))
goto err;
}

if (f->buf_idx2 != -1) {
base = be32_to_cpu(args->args[f->buf_idx2]);
if (f->size_idx2 != -1)
size = be32_to_cpu(args->args[f->size_idx2]);
else if (f->fixed_size)
size = f->fixed_size;
else
size = 1;
end = base + size - 1;

/*
* Special case for ibm,configure-connector where the
* address can be 0
*/
if (!strcmp(f->name, "ibm,configure-connector") &&
base == 0)
return false;

if (!in_rmo_buf(base, end))
goto err;
}

return false;
}

err:
pr_err_ratelimited("sys_rtas: RTAS call blocked - exploit attempt?\n");
pr_err_ratelimited("sys_rtas: token=0x%x, nargs=%d (called by %s)\n",
token, nargs, current->comm);
return true;
}

#else

static bool block_rtas_call(int token, int nargs,
struct rtas_args *args)
{
return false;
}

#endif /* CONFIG_PPC_RTAS_FILTER */

/* We assume to be passed big endian arguments */
asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
{
Expand Down Expand Up @@ -1082,6 +1223,9 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
args.rets = &args.args[nargs];
memset(args.rets, 0, nret * sizeof(rtas_arg_t));

if (block_rtas_call(token, nargs, &args))
return -EINVAL;

/* Need to handle ibm,suspend_me call specially */
if (token == ibm_suspend_me_token) {

Expand Down Expand Up @@ -1141,6 +1285,9 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
void __init rtas_initialize(void)
{
unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
#ifdef CONFIG_PPC_RTAS_FILTER
int i;
#endif

/* Get RTAS dev node and fill up our "rtas" structure with infos
* about it.
Expand Down Expand Up @@ -1180,6 +1327,12 @@ void __init rtas_initialize(void)
#ifdef CONFIG_RTAS_ERROR_LOGGING
rtas_last_error_token = rtas_token("rtas-last-error");
#endif

#ifdef CONFIG_PPC_RTAS_FILTER
for (i = 0; i < ARRAY_SIZE(rtas_filters); i++) {
rtas_filters[i].token = rtas_token(rtas_filters[i].name);
}
#endif
}

int __init early_init_dt_scan_rtas(unsigned long node,
Expand Down
11 changes: 10 additions & 1 deletion arch/x86/net/bpf_jit_comp.c
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,16 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i];
}
ilen = prog - temp;
if (image) {
if (unlikely(proglen + ilen > oldproglen)) {
/*
* When populating the image, assert that:
*
* i) We do not write beyond the allocated space, and
* ii) addrs[i] did not change from the prior run, in order
* to validate assumptions made for computing branch
* displacements.
*/
if (unlikely(proglen + ilen > oldproglen ||
proglen + ilen != addrs[i])) {
pr_err("bpb_jit_compile fatal error\n");
kfree(addrs);
module_free(NULL, image);
Expand Down
9 changes: 4 additions & 5 deletions drivers/infiniband/hw/mlx5/cq.c
Original file line number Diff line number Diff line change
Expand Up @@ -802,15 +802,14 @@ static void destroy_cq_user(struct mlx5_ib_cq *cq, struct ib_ucontext *context)
ib_umem_release(cq->buf.umem);
}

static void init_cq_frag_buf(struct mlx5_ib_cq *cq,
struct mlx5_ib_cq_buf *buf)
static void init_cq_frag_buf(struct mlx5_ib_cq_buf *buf)
{
int i;
void *cqe;
struct mlx5_cqe64 *cqe64;

for (i = 0; i < buf->nent; i++) {
cqe = get_cqe(cq, i);
cqe = mlx5_frag_buf_get_wqe(&buf->fbc, i);
cqe64 = buf->cqe_size == 64 ? cqe : cqe + 64;
cqe64->op_own = MLX5_CQE_INVALID << 4;
}
Expand All @@ -836,7 +835,7 @@ static int create_cq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *cq,
if (err)
goto err_db;

init_cq_frag_buf(cq, &cq->buf);
init_cq_frag_buf(&cq->buf);

*inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
MLX5_FLD_SZ_BYTES(create_cq_in, pas[0]) *
Expand Down Expand Up @@ -1159,7 +1158,7 @@ static int resize_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *cq,
if (err)
goto ex;

init_cq_frag_buf(cq, cq->resize_buf);
init_cq_frag_buf(cq->resize_buf);

return 0;

Expand Down
6 changes: 4 additions & 2 deletions drivers/net/ethernet/emulex/benet/be_cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ int be_process_mcc(struct be_adapter *adapter)
int num = 0, status = 0;
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;

spin_lock_bh(&adapter->mcc_cq_lock);
spin_lock(&adapter->mcc_cq_lock);

while ((compl = be_mcc_compl_get(adapter))) {
if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
Expand All @@ -570,7 +570,7 @@ int be_process_mcc(struct be_adapter *adapter)
if (num)
be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);

spin_unlock_bh(&adapter->mcc_cq_lock);
spin_unlock(&adapter->mcc_cq_lock);
return status;
}

Expand All @@ -585,7 +585,9 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
if (be_check_error(adapter, BE_ERROR_ANY))
return -EIO;

local_bh_disable();
status = be_process_mcc(adapter);
local_bh_enable();

if (atomic_read(&mcc_obj->q.used) == 0)
break;
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/emulex/benet/be_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5623,7 +5623,9 @@ static void be_worker(struct work_struct *work)
* mcc completions
*/
if (!netif_running(adapter->netdev)) {
local_bh_disable();
be_process_mcc(adapter);
local_bh_enable();
goto reschedule;
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -934,8 +934,8 @@ s32 ixgbe_mii_bus_init(struct ixgbe_hw *hw)
}

/* Use the position of the device in the PCI hierarchy as the id */
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%x", ixgbe_driver_name,
(pdev->bus->number << 8) | pdev->devfn);
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%.8s%02x", ixgbe_driver_name,
pci_name(pdev), pdev->devfn);

bus->name = "ixgbe-mdio";
bus->priv = adapter;
Expand Down
5 changes: 2 additions & 3 deletions drivers/scsi/lpfc/lpfc_sli.c
Original file line number Diff line number Diff line change
Expand Up @@ -1275,7 +1275,6 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
goto out;
}

pring = phba->sli4_hba.els_wq->pring;
if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) &&
(sglq->state != SGL_XRI_ABORTED)) {
spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock,
Expand All @@ -1293,9 +1292,9 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
&phba->sli4_hba.lpfc_els_sgl_list);
spin_unlock_irqrestore(
&phba->sli4_hba.sgl_list_lock, iflag);

pring = lpfc_phba_elsring(phba);
/* Check if TXQ queue needs to be serviced */
if (!list_empty(&pring->txq))
if (pring && (!list_empty(&pring->txq)))
lpfc_worker_wake_up(phba);
}
}
Expand Down
29 changes: 23 additions & 6 deletions fs/xfs/xfs_log.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,25 @@ xlog_tic_add_region(xlog_ticket_t *tic, uint len, uint type)
tic->t_res_num++;
}

bool
xfs_log_writable(
struct xfs_mount *mp)
{
/*
* Never write to the log on norecovery mounts, if the block device is
* read-only, or if the filesystem is shutdown. Read-only mounts still
* allow internal writes for log recovery and unmount purposes, so don't
* restrict that case here.
*/
if (mp->m_flags & XFS_MOUNT_NORECOVERY)
return false;
if (xfs_readonly_buftarg(mp->m_log->l_targ))
return false;
if (XFS_FORCED_SHUTDOWN(mp))
return false;
return true;
}

/*
* Replenish the byte reservation required by moving the grant write head.
*/
Expand Down Expand Up @@ -837,14 +856,12 @@ xfs_log_unmount_write(xfs_mount_t *mp)
int error;

/*
* Don't write out unmount record on norecovery mounts or ro devices.
* Or, if we are doing a forced umount (typically because of IO errors).
* RHEL7: Doesn't really matter what we return here, the only caller
* ignores the return value and upstream version is already a void
* funciton
*/
if (mp->m_flags & XFS_MOUNT_NORECOVERY ||
xfs_readonly_buftarg(log->l_mp->m_logdev_targp)) {
ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
if (!xfs_log_writable(mp))
return 0;
}

error = xfs_log_force(mp, XFS_LOG_SYNC);
ASSERT(error || !(XLOG_FORCED_SHUTDOWN(log)));
Expand Down
1 change: 1 addition & 0 deletions fs/xfs/xfs_log.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ int xfs_log_reserve(struct xfs_mount *mp,
int xfs_log_regrant(struct xfs_mount *mp, struct xlog_ticket *tic);
void xfs_log_unmount(struct xfs_mount *mp);
int xfs_log_force_umount(struct xfs_mount *mp, int logerror);
bool xfs_log_writable(struct xfs_mount *mp);

struct xlog_ticket *xfs_log_ticket_get(struct xlog_ticket *ticket);
void xfs_log_ticket_put(struct xlog_ticket *ticket);
Expand Down
3 changes: 1 addition & 2 deletions fs/xfs/xfs_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -1169,8 +1169,7 @@ xfs_fs_writable(
int
xfs_log_sbcount(xfs_mount_t *mp)
{
/* allow this to proceed during the freeze sequence... */
if (!xfs_fs_writable(mp, SB_FREEZE_COMPLETE))
if (!xfs_log_writable(mp))
return 0;

/*
Expand Down
Loading

0 comments on commit 0ebba03

Please sign in to comment.