/* * Proc regrdwr file write handler. * * This function is called when the 'regrdwr' file is opened for writing * * This function can be used to write to a register. */ static ssize_t mwifiex_regrdwr_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { char *buf; int ret; u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX; buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); if (IS_ERR(buf)) return PTR_ERR(buf); sscanf(buf, "%u %x %x", ®_type, ®_offset, ®_value); if (reg_type == 0 || reg_offset == 0) { ret = -EINVAL; goto done; } else { saved_reg_type = reg_type; saved_reg_offset = reg_offset; saved_reg_value = reg_value; ret = count; } done: kfree(buf); return ret; }
static ssize_t cec_error_inj_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct seq_file *sf = file->private_data; struct cec_adapter *adap = sf->private; char *buf; char *line; char *p; buf = memdup_user_nul(ubuf, min_t(size_t, PAGE_SIZE, count)); if (IS_ERR(buf)) return PTR_ERR(buf); p = buf; while (p && *p) { p = skip_spaces(p); line = strsep(&p, "\n"); if (!*line || *line == '#') continue; if (!adap->ops->error_inj_parse_line(adap, line)) { kfree(buf); return -EINVAL; } } kfree(buf); return count; }
/* * Proc rdeeprom file write handler. * * This function is called when the 'rdeeprom' file is opened for writing * * This function can be used to write to a RDEEPROM location. */ static ssize_t mwifiex_rdeeprom_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { char *buf; int ret = 0; int offset = -1, bytes = -1; buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); if (IS_ERR(buf)) return PTR_ERR(buf); sscanf(buf, "%d %d", &offset, &bytes); if (offset == -1 || bytes == -1) { ret = -EINVAL; goto done; } else { saved_offset = offset; saved_bytes = bytes; ret = count; } done: kfree(buf); return ret; }
static ssize_t display_crc_ctl_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) { struct seq_file *m = file->private_data; struct drm_i915_private *dev_priv = m->private; char *tmpbuf; int ret; if (len == 0) return 0; if (len > PAGE_SIZE - 1) { DRM_DEBUG_DRIVER("expected <%lu bytes into pipe crc control\n", PAGE_SIZE); return -E2BIG; } tmpbuf = memdup_user_nul(ubuf, len); if (IS_ERR(tmpbuf)) return PTR_ERR(tmpbuf); ret = display_crc_ctl_parse(dev_priv, tmpbuf, len); kfree(tmpbuf); if (ret < 0) return ret; *offp += len; return len; }
/* Copy in a whole string from userspace into kernelspace. */ static char * copyin_string(char __user *user, size_t len) { if ((ssize_t)len < 0 || (ssize_t)(len + 1) < 0) return ERR_PTR(-EINVAL); return memdup_user_nul(user, len); }
static ssize_t sel_write_avc_cache_threshold(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char *page; ssize_t ret; unsigned int new_value; ret = task_has_security(current, SECURITY__SETSECPARAM); if (ret) return ret; if (count >= PAGE_SIZE) return -ENOMEM; /* No partial writes. */ if (*ppos != 0) return -EINVAL; page = memdup_user_nul(buf, count); if (IS_ERR(page)) return PTR_ERR(page); ret = -EINVAL; if (sscanf(page, "%u", &new_value) != 1) goto out; avc_cache_threshold = new_value; ret = count; out: kfree(page); return ret; }
static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char *page; ssize_t length; unsigned int new_value; length = task_has_security(current, SECURITY__SETCHECKREQPROT); if (length) return length; if (count >= PAGE_SIZE) return -ENOMEM; /* No partial writes. */ if (*ppos != 0) return -EINVAL; page = memdup_user_nul(buf, count); if (IS_ERR(page)) return PTR_ERR(page); length = -EINVAL; if (sscanf(page, "%u", &new_value) != 1) goto out; selinux_checkreqprot = new_value ? 1 : 0; length = count; out: kfree(page); return length; }
static ssize_t lbs_wrrf_write(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { struct lbs_private *priv = file->private_data; ssize_t res; u32 offset, value; char *buf; buf = memdup_user_nul(userbuf, min(count, len - 1)); if (IS_ERR(buf)) return PTR_ERR(buf); res = sscanf(buf, "%x %x", &offset, &value); if (res != 2) { res = -EFAULT; goto out_unlock; } res = lbs_set_reg(priv, CMD_RF_REG_ACCESS, offset, value); mdelay(10); if (!res) res = count; out_unlock: kfree(buf); return res; }
/*---write channel 1..4 to rxon for it, 0 to rxoff---*/ static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf, size_t len, loff_t *ppos) { struct wil6210_priv *wil = file->private_data; int rc; long channel; bool on; char *kbuf = memdup_user_nul(buf, len); if (IS_ERR(kbuf)) return PTR_ERR(kbuf); rc = kstrtol(kbuf, 0, &channel); kfree(kbuf); if (rc) return rc; if ((channel < 0) || (channel > 4)) { wil_err(wil, "Invalid channel %ld\n", channel); return -EINVAL; } on = !!channel; if (on) { rc = wmi_set_channel(wil, (int)channel); if (rc) return rc; } rc = wmi_rxon(wil, on); if (rc) return rc; return len; }
/* Proc hscfg file write handler * This function can be used to configure the host sleep parameters. */ static ssize_t mwifiex_hscfg_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct mwifiex_private *priv = (void *)file->private_data; char *buf; int ret, arg_num; struct mwifiex_ds_hs_cfg hscfg; int conditions = HS_CFG_COND_DEF; u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF; buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); if (IS_ERR(buf)) return PTR_ERR(buf); arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap); memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg)); if (arg_num > 3) { mwifiex_dbg(priv->adapter, ERROR, "Too many arguments\n"); ret = -EINVAL; goto done; } if (arg_num >= 1 && arg_num < 3) mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET, MWIFIEX_SYNC_CMD, &hscfg); if (arg_num) { if (conditions == HS_CFG_CANCEL) { mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD); ret = count; goto done; } hscfg.conditions = conditions; } if (arg_num >= 2) hscfg.gpio = gpio; if (arg_num == 3) hscfg.gap = gap; hscfg.is_invoke_hostcmd = false; mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD, &hscfg); mwifiex_enable_hs(priv->adapter); priv->adapter->hs_enabling = false; ret = count; done: kfree(buf); return ret; }
static ssize_t sel_write_bool(struct file *filep, const char __user *buf, size_t count, loff_t *ppos) { char *page = NULL; ssize_t length; int new_value; unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; const char *name = filep->f_path.dentry->d_name.name; mutex_lock(&sel_mutex); length = avc_has_perm(current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETBOOL, NULL); if (length) goto out; length = -EINVAL; if (index >= bool_num || strcmp(name, bool_pending_names[index])) goto out; length = -ENOMEM; if (count >= PAGE_SIZE) goto out; /* No partial writes. */ length = -EINVAL; if (*ppos != 0) goto out; page = memdup_user_nul(buf, count); if (IS_ERR(page)) { length = PTR_ERR(page); page = NULL; goto out; } length = -EINVAL; if (sscanf(page, "%d", &new_value) != 1) goto out; if (new_value) new_value = 1; bool_pending_values[index] = new_value; length = count; out: mutex_unlock(&sel_mutex); kfree(page); return length; }
static ssize_t lbs_rdrf_write(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { struct lbs_private *priv = file->private_data; char *buf; buf = memdup_user_nul(userbuf, min(count, len - 1)); if (IS_ERR(buf)) return PTR_ERR(buf); priv->rf_offset = simple_strtoul(buf, NULL, 16); kfree(buf); return count; }
/* Copy in a whole string from userspace into kernelspace. */ static int copyin_string(char __user *user, size_t len, char **ptr) { char *tmp; if ((ssize_t)len < 0 || (ssize_t)(len + 1) < 0) return -EINVAL; tmp = memdup_user_nul(user, len); if (IS_ERR(tmp)) return PTR_ERR(tmp); *ptr = tmp; return 0; }
/** * lbs_debugfs_write - proc write function * * @f: file pointer * @buf: pointer to data buffer * @cnt: data number to write * @ppos: file position * * returns: amount of data written */ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, size_t cnt, loff_t *ppos) { int r, i; char *pdata; char *p; char *p0; char *p1; char *p2; struct debug_data *d = f->private_data; if (cnt == 0) return 0; pdata = memdup_user_nul(buf, cnt); if (IS_ERR(pdata)) return PTR_ERR(pdata); p0 = pdata; for (i = 0; i < num_of_items; i++) { do { p = strstr(p0, d[i].name); if (p == NULL) break; p1 = strchr(p, '\n'); if (p1 == NULL) break; p0 = p1++; p2 = strchr(p, '='); if (!p2) break; p2++; r = simple_strtoul(p2, NULL, 0); if (d[i].size == 1) *((u8 *) d[i].addr) = (u8) r; else if (d[i].size == 2) *((u16 *) d[i].addr) = (u16) r; else if (d[i].size == 4) *((u32 *) d[i].addr) = (u32) r; else if (d[i].size == 8) *((u64 *) d[i].addr) = (u64) r; break; } while (1); } kfree(pdata); return (ssize_t)cnt; }
static ssize_t sel_commit_bools_write(struct file *filep, const char __user *buf, size_t count, loff_t *ppos) { char *page = NULL; ssize_t length; int new_value; mutex_lock(&sel_mutex); length = avc_has_perm(current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETBOOL, NULL); if (length) goto out; length = -ENOMEM; if (count >= PAGE_SIZE) goto out; /* No partial writes. */ length = -EINVAL; if (*ppos != 0) goto out; page = memdup_user_nul(buf, count); if (IS_ERR(page)) { length = PTR_ERR(page); page = NULL; goto out; } length = -EINVAL; if (sscanf(page, "%d", &new_value) != 1) goto out; length = 0; if (new_value && bool_pending_values) length = security_set_bools(bool_num, bool_pending_values); if (!length) length = count; out: mutex_unlock(&sel_mutex); kfree(page); return length; }
static ssize_t sel_write_enforce(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char *page = NULL; ssize_t length; int new_value; if (count >= PAGE_SIZE) return -ENOMEM; /* No partial writes. */ if (*ppos != 0) return -EINVAL; page = memdup_user_nul(buf, count); if (IS_ERR(page)) return PTR_ERR(page); length = -EINVAL; if (sscanf(page, "%d", &new_value) != 1) goto out; new_value = !!new_value; if (new_value != selinux_enforcing) { length = avc_has_perm(current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETENFORCE, NULL); if (length) goto out; audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, "enforcing=%d old_enforcing=%d auid=%u ses=%u", new_value, selinux_enforcing, from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); selinux_enforcing = new_value; if (selinux_enforcing) avc_ss_reset(0); selnl_notify_setenforce(selinux_enforcing); selinux_status_update_setenforce(selinux_enforcing); } length = count; out: kfree(page); return length; }
/* Proc memrw file write handler. * This function is called when the 'memrw' file is opened for writing * This function can be used to write to a memory location. */ static ssize_t mwifiex_memrw_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { int ret; char cmd; struct mwifiex_ds_mem_rw mem_rw; u16 cmd_action; struct mwifiex_private *priv = (void *)file->private_data; char *buf; buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); if (IS_ERR(buf)) return PTR_ERR(buf); ret = sscanf(buf, "%c %x %x", &cmd, &mem_rw.addr, &mem_rw.value); if (ret != 3) { ret = -EINVAL; goto done; } if ((cmd == 'r') || (cmd == 'R')) { cmd_action = HostCmd_ACT_GEN_GET; mem_rw.value = 0; } else if ((cmd == 'w') || (cmd == 'W')) { cmd_action = HostCmd_ACT_GEN_SET; } else { ret = -EINVAL; goto done; } memcpy(&priv->mem_rw, &mem_rw, sizeof(mem_rw)); if (mwifiex_send_cmd(priv, HostCmd_CMD_MEM_ACCESS, cmd_action, 0, &mem_rw, true)) ret = -1; else ret = count; done: kfree(buf); return ret; }
static ssize_t lbs_host_sleep_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct lbs_private *priv = file->private_data; ssize_t ret; int host_sleep; char *buf; buf = memdup_user_nul(user_buf, min(count, len - 1)); if (IS_ERR(buf)) return PTR_ERR(buf); ret = sscanf(buf, "%d", &host_sleep); if (ret != 1) { ret = -EINVAL; goto out_unlock; } if (host_sleep == 0) ret = lbs_set_host_sleep(priv, 0); else if (host_sleep == 1) { if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { netdev_info(priv->dev, "wake parameters not configured\n"); ret = -EINVAL; goto out_unlock; } ret = lbs_set_host_sleep(priv, 1); } else { netdev_err(priv->dev, "invalid option\n"); ret = -EINVAL; } if (!ret) ret = count; out_unlock: kfree(buf); return ret; }
static ssize_t crc_control_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) { struct seq_file *m = file->private_data; struct drm_crtc *crtc = m->private; struct drm_crtc_crc *crc = &crtc->crc; char *source; if (len == 0) return 0; if (len > PAGE_SIZE - 1) { DRM_DEBUG_KMS("Expected < %lu bytes into crtc crc control\n", PAGE_SIZE); return -E2BIG; } source = memdup_user_nul(ubuf, len); if (IS_ERR(source)) return PTR_ERR(source); if (source[len] == '\n') source[len] = '\0'; spin_lock_irq(&crc->lock); if (crc->opened) { spin_unlock_irq(&crc->lock); kfree(source); return -EBUSY; } kfree(crc->source); crc->source = source; spin_unlock_irq(&crc->lock); *offp += len; return len; }
static ssize_t sel_write_disable(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char *page; ssize_t length; int new_value; if (count >= PAGE_SIZE) return -ENOMEM; /* No partial writes. */ if (*ppos != 0) return -EINVAL; page = memdup_user_nul(buf, count); if (IS_ERR(page)) return PTR_ERR(page); length = -EINVAL; if (sscanf(page, "%d", &new_value) != 1) goto out; if (new_value) { length = selinux_disable(); if (length) goto out; audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, "selinux=0 auid=%u ses=%u", from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); } length = count; out: kfree(page); return length; }
/* Proc debug_mask file read handler. * This function is called when the 'debug_mask' file is opened for reading * This function can be used read driver debugging mask value. */ static ssize_t mwifiex_debug_mask_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { int ret; unsigned long debug_mask; struct mwifiex_private *priv = (void *)file->private_data; char *buf; buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); if (IS_ERR(buf)) return PTR_ERR(buf); if (kstrtoul(buf, 0, &debug_mask)) { ret = -EINVAL; goto done; } priv->adapter->debug_mask = debug_mask; ret = count; done: kfree(buf); return ret; }
static ssize_t lbs_sleepparams_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct lbs_private *priv = file->private_data; ssize_t ret; struct sleep_params sp; int p1, p2, p3, p4, p5, p6; char *buf; buf = memdup_user_nul(user_buf, min(count, len - 1)); if (IS_ERR(buf)) return PTR_ERR(buf); ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6); if (ret != 6) { ret = -EINVAL; goto out_unlock; } sp.sp_error = p1; sp.sp_offset = p2; sp.sp_stabletime = p3; sp.sp_calcontrol = p4; sp.sp_extsleepclk = p5; sp.sp_reserved = p6; ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_SET, &sp); if (!ret) ret = count; else if (ret > 0) ret = -EINVAL; out_unlock: kfree(buf); return ret; }
/* * command the cache */ static ssize_t cachefiles_daemon_write(struct file *file, const char __user *_data, size_t datalen, loff_t *pos) { const struct cachefiles_daemon_cmd *cmd; struct cachefiles_cache *cache = file->private_data; ssize_t ret; char *data, *args, *cp; //_enter(",,%zu,", datalen); ASSERT(cache); if (test_bit(CACHEFILES_DEAD, &cache->flags)) return -EIO; if (datalen < 0 || datalen > PAGE_SIZE - 1) return -EOPNOTSUPP; /* drag the command string into the kernel so we can parse it */ data = memdup_user_nul(_data, datalen); if (IS_ERR(data)) return PTR_ERR(data); ret = -EINVAL; if (memchr(data, '\0', datalen)) goto error; /* strip any newline */ cp = memchr(data, '\n', datalen); if (cp) { if (cp == data) goto error; *cp = '\0'; } /* parse the command */ ret = -EOPNOTSUPP; for (args = data; *args; args++) if (isspace(*args)) break; if (*args) { if (args == data) goto error; *args = '\0'; args = skip_spaces(++args); } /* run the appropriate command handler */ for (cmd = cachefiles_daemon_cmds; cmd->name[0]; cmd++) if (strcmp(cmd->name, data) == 0) goto found_command; error: kfree(data); //_leave(" = %zd", ret); return ret; found_command: mutex_lock(&cache->daemon_mutex); ret = -EIO; if (!test_bit(CACHEFILES_DEAD, &cache->flags)) ret = cmd->handler(cache, args); mutex_unlock(&cache->daemon_mutex); if (ret == 0) ret = datalen; goto error; }
static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask, struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { struct cmd_ds_802_11_subscribe_event *events; struct mrvl_ie_thresholds *tlv; struct lbs_private *priv = file->private_data; int value, freq, new_mask; uint16_t curr_mask; char *buf; int ret; buf = memdup_user_nul(userbuf, min(count, len - 1)); if (IS_ERR(buf)) return PTR_ERR(buf); ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask); if (ret != 3) { ret = -EINVAL; goto out_page; } events = kzalloc(sizeof(*events), GFP_KERNEL); if (!events) { ret = -ENOMEM; goto out_page; } events->hdr.size = cpu_to_le16(sizeof(*events)); events->action = cpu_to_le16(CMD_ACT_GET); ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events); if (ret) goto out_events; curr_mask = le16_to_cpu(events->events); if (new_mask) new_mask = curr_mask | event_mask; else new_mask = curr_mask & ~event_mask; /* Now everything is set and we can send stuff down to the firmware */ tlv = (void *)events->tlv; events->action = cpu_to_le16(CMD_ACT_SET); events->events = cpu_to_le16(new_mask); tlv->header.type = cpu_to_le16(tlv_type); tlv->header.len = cpu_to_le16(sizeof(*tlv) - sizeof(tlv->header)); tlv->value = value; if (tlv_type != TLV_TYPE_BCNMISS) tlv->freq = freq; /* The command header, the action, the event mask, and one TLV */ events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 4 + sizeof(*tlv)); ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events); if (!ret) ret = count; out_events: kfree(events); out_page: kfree(buf); return ret; }