|
@@ -46,6 +46,9 @@ static int seq_open_net(struct inode *inode, struct file *file)
|
|
|
|
|
|
WARN_ON_ONCE(state_size < sizeof(*p));
|
|
|
|
|
|
+ if (file->f_mode & FMODE_WRITE && !PDE(inode)->write)
|
|
|
+ return -EACCES;
|
|
|
+
|
|
|
net = get_proc_net(inode);
|
|
|
if (!net)
|
|
|
return -ENXIO;
|
|
@@ -73,6 +76,7 @@ static int seq_release_net(struct inode *ino, struct file *f)
|
|
|
static const struct file_operations proc_net_seq_fops = {
|
|
|
.open = seq_open_net,
|
|
|
.read = seq_read,
|
|
|
+ .write = proc_simple_write,
|
|
|
.llseek = seq_lseek,
|
|
|
.release = seq_release_net,
|
|
|
};
|
|
@@ -93,6 +97,50 @@ struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(proc_create_net_data);
|
|
|
|
|
|
+/**
|
|
|
+ * proc_create_net_data_write - Create a writable net_ns-specific proc file
|
|
|
+ * @name: The name of the file.
|
|
|
+ * @mode: The file's access mode.
|
|
|
+ * @parent: The parent directory in which to create.
|
|
|
+ * @ops: The seq_file ops with which to read the file.
|
|
|
+ * @write: The write method which which to 'modify' the file.
|
|
|
+ * @data: Data for retrieval by PDE_DATA().
|
|
|
+ *
|
|
|
+ * Create a network namespaced proc file in the @parent directory with the
|
|
|
+ * specified @name and @mode that allows reading of a file that displays a
|
|
|
+ * series of elements and also provides for the file accepting writes that have
|
|
|
+ * some arbitrary effect.
|
|
|
+ *
|
|
|
+ * The functions in the @ops table are used to iterate over items to be
|
|
|
+ * presented and extract the readable content using the seq_file interface.
|
|
|
+ *
|
|
|
+ * The @write function is called with the data copied into a kernel space
|
|
|
+ * scratch buffer and has a NUL appended for convenience. The buffer may be
|
|
|
+ * modified by the @write function. @write should return 0 on success.
|
|
|
+ *
|
|
|
+ * The @data value is accessible from the @show and @write functions by calling
|
|
|
+ * PDE_DATA() on the file inode. The network namespace must be accessed by
|
|
|
+ * calling seq_file_net() on the seq_file struct.
|
|
|
+ */
|
|
|
+struct proc_dir_entry *proc_create_net_data_write(const char *name, umode_t mode,
|
|
|
+ struct proc_dir_entry *parent,
|
|
|
+ const struct seq_operations *ops,
|
|
|
+ proc_write_t write,
|
|
|
+ unsigned int state_size, void *data)
|
|
|
+{
|
|
|
+ struct proc_dir_entry *p;
|
|
|
+
|
|
|
+ p = proc_create_reg(name, mode, &parent, data);
|
|
|
+ if (!p)
|
|
|
+ return NULL;
|
|
|
+ p->proc_fops = &proc_net_seq_fops;
|
|
|
+ p->seq_ops = ops;
|
|
|
+ p->state_size = state_size;
|
|
|
+ p->write = write;
|
|
|
+ return proc_register(parent, p);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(proc_create_net_data_write);
|
|
|
+
|
|
|
static int single_open_net(struct inode *inode, struct file *file)
|
|
|
{
|
|
|
struct proc_dir_entry *de = PDE(inode);
|
|
@@ -119,6 +167,7 @@ static int single_release_net(struct inode *ino, struct file *f)
|
|
|
static const struct file_operations proc_net_single_fops = {
|
|
|
.open = single_open_net,
|
|
|
.read = seq_read,
|
|
|
+ .write = proc_simple_write,
|
|
|
.llseek = seq_lseek,
|
|
|
.release = single_release_net,
|
|
|
};
|
|
@@ -138,6 +187,49 @@ struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(proc_create_net_single);
|
|
|
|
|
|
+/**
|
|
|
+ * proc_create_net_single_write - Create a writable net_ns-specific proc file
|
|
|
+ * @name: The name of the file.
|
|
|
+ * @mode: The file's access mode.
|
|
|
+ * @parent: The parent directory in which to create.
|
|
|
+ * @show: The seqfile show method with which to read the file.
|
|
|
+ * @write: The write method which which to 'modify' the file.
|
|
|
+ * @data: Data for retrieval by PDE_DATA().
|
|
|
+ *
|
|
|
+ * Create a network-namespaced proc file in the @parent directory with the
|
|
|
+ * specified @name and @mode that allows reading of a file that displays a
|
|
|
+ * single element rather than a series and also provides for the file accepting
|
|
|
+ * writes that have some arbitrary effect.
|
|
|
+ *
|
|
|
+ * The @show function is called to extract the readable content via the
|
|
|
+ * seq_file interface.
|
|
|
+ *
|
|
|
+ * The @write function is called with the data copied into a kernel space
|
|
|
+ * scratch buffer and has a NUL appended for convenience. The buffer may be
|
|
|
+ * modified by the @write function. @write should return 0 on success.
|
|
|
+ *
|
|
|
+ * The @data value is accessible from the @show and @write functions by calling
|
|
|
+ * PDE_DATA() on the file inode. The network namespace must be accessed by
|
|
|
+ * calling seq_file_single_net() on the seq_file struct.
|
|
|
+ */
|
|
|
+struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mode,
|
|
|
+ struct proc_dir_entry *parent,
|
|
|
+ int (*show)(struct seq_file *, void *),
|
|
|
+ proc_write_t write,
|
|
|
+ void *data)
|
|
|
+{
|
|
|
+ struct proc_dir_entry *p;
|
|
|
+
|
|
|
+ p = proc_create_reg(name, mode, &parent, data);
|
|
|
+ if (!p)
|
|
|
+ return NULL;
|
|
|
+ p->proc_fops = &proc_net_single_fops;
|
|
|
+ p->single_show = show;
|
|
|
+ p->write = write;
|
|
|
+ return proc_register(parent, p);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(proc_create_net_single_write);
|
|
|
+
|
|
|
static struct net *get_proc_task_net(struct inode *dir)
|
|
|
{
|
|
|
struct task_struct *task;
|