aboutsummaryrefslogtreecommitdiff
path: root/fs/isofs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/isofs')
-rw-r--r--fs/isofs/compress.c2
-rw-r--r--fs/isofs/dir.c42
-rw-r--r--fs/isofs/export.c20
-rw-r--r--fs/isofs/inode.c108
-rw-r--r--fs/isofs/isofs.h6
-rw-r--r--fs/isofs/namei.c5
-rw-r--r--fs/isofs/rock.c4
7 files changed, 84 insertions, 103 deletions
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c
index 0b3fa7974fa..592e5115a56 100644
--- a/fs/isofs/compress.c
+++ b/fs/isofs/compress.c
@@ -296,7 +296,7 @@ static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,
*/
static int zisofs_readpage(struct file *file, struct page *page)
{
- struct inode *inode = file->f_path.dentry->d_inode;
+ struct inode *inode = file_inode(file);
struct address_space *mapping = inode->i_mapping;
int err;
int i, pcount, full_page;
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index f20437c068a..b943cbd963b 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -78,8 +78,8 @@ int get_acorn_filename(struct iso_directory_record *de,
/*
* This should _really_ be cleaned up some day..
*/
-static int do_isofs_readdir(struct inode *inode, struct file *filp,
- void *dirent, filldir_t filldir,
+static int do_isofs_readdir(struct inode *inode, struct file *file,
+ struct dir_context *ctx,
char *tmpname, struct iso_directory_record *tmpde)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
@@ -94,10 +94,10 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
struct iso_directory_record *de;
struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
- offset = filp->f_pos & (bufsize - 1);
- block = filp->f_pos >> bufbits;
+ offset = ctx->pos & (bufsize - 1);
+ block = ctx->pos >> bufbits;
- while (filp->f_pos < inode->i_size) {
+ while (ctx->pos < inode->i_size) {
int de_len;
if (!bh) {
@@ -108,7 +108,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
de = (struct iso_directory_record *) (bh->b_data + offset);
- de_len = *(unsigned char *) de;
+ de_len = *(unsigned char *)de;
/*
* If the length byte is zero, we should move on to the next
@@ -119,8 +119,8 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
if (de_len == 0) {
brelse(bh);
bh = NULL;
- filp->f_pos = (filp->f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
- block = filp->f_pos >> bufbits;
+ ctx->pos = (ctx->pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
+ block = ctx->pos >> bufbits;
offset = 0;
continue;
}
@@ -164,16 +164,16 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
if (de->flags[-sbi->s_high_sierra] & 0x80) {
first_de = 0;
- filp->f_pos += de_len;
+ ctx->pos += de_len;
continue;
}
first_de = 1;
/* Handle the case of the '.' directory */
if (de->name_len[0] == 1 && de->name[0] == 0) {
- if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0)
+ if (!dir_emit_dot(file, ctx))
break;
- filp->f_pos += de_len;
+ ctx->pos += de_len;
continue;
}
@@ -181,10 +181,9 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
/* Handle the case of the '..' directory */
if (de->name_len[0] == 1 && de->name[0] == 1) {
- inode_number = parent_ino(filp->f_path.dentry);
- if (filldir(dirent, "..", 2, filp->f_pos, inode_number, DT_DIR) < 0)
+ if (!dir_emit_dotdot(file, ctx))
break;
- filp->f_pos += de_len;
+ ctx->pos += de_len;
continue;
}
@@ -198,7 +197,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
if ((sbi->s_hide && (de->flags[-sbi->s_high_sierra] & 1)) ||
(!sbi->s_showassoc &&
(de->flags[-sbi->s_high_sierra] & 4))) {
- filp->f_pos += de_len;
+ ctx->pos += de_len;
continue;
}
@@ -230,10 +229,10 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
}
}
if (len > 0) {
- if (filldir(dirent, p, len, filp->f_pos, inode_number, DT_UNKNOWN) < 0)
+ if (!dir_emit(ctx, p, len, inode_number, DT_UNKNOWN))
break;
}
- filp->f_pos += de_len;
+ ctx->pos += de_len;
continue;
}
@@ -247,13 +246,12 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
* handling split directory entries.. The real work is done by
* "do_isofs_readdir()".
*/
-static int isofs_readdir(struct file *filp,
- void *dirent, filldir_t filldir)
+static int isofs_readdir(struct file *file, struct dir_context *ctx)
{
int result;
char *tmpname;
struct iso_directory_record *tmpde;
- struct inode *inode = filp->f_path.dentry->d_inode;
+ struct inode *inode = file_inode(file);
tmpname = (char *)__get_free_page(GFP_KERNEL);
if (tmpname == NULL)
@@ -261,7 +259,7 @@ static int isofs_readdir(struct file *filp,
tmpde = (struct iso_directory_record *) (tmpname+1024);
- result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
+ result = do_isofs_readdir(inode, file, ctx, tmpname, tmpde);
free_page((unsigned long) tmpname);
return result;
@@ -271,7 +269,7 @@ const struct file_operations isofs_dir_operations =
{
.llseek = generic_file_llseek,
.read = generic_read_dir,
- .readdir = isofs_readdir,
+ .iterate = isofs_readdir,
};
/*
diff --git a/fs/isofs/export.c b/fs/isofs/export.c
index dd4687ff30d..12088d8de3f 100644
--- a/fs/isofs/export.c
+++ b/fs/isofs/export.c
@@ -107,12 +107,11 @@ static struct dentry *isofs_export_get_parent(struct dentry *child)
}
static int
-isofs_export_encode_fh(struct dentry *dentry,
+isofs_export_encode_fh(struct inode *inode,
__u32 *fh32,
int *max_len,
- int connectable)
+ struct inode *parent)
{
- struct inode * inode = dentry->d_inode;
struct iso_inode_info * ei = ISOFS_I(inode);
int len = *max_len;
int type = 1;
@@ -124,28 +123,25 @@ isofs_export_encode_fh(struct dentry *dentry,
* offset of the inode and the upper 16 bits of fh32[1] to
* hold the offset of the parent.
*/
- if (connectable && (len < 5)) {
+ if (parent && (len < 5)) {
*max_len = 5;
- return 255;
+ return FILEID_INVALID;
} else if (len < 3) {
*max_len = 3;
- return 255;
+ return FILEID_INVALID;
}
len = 3;
fh32[0] = ei->i_iget5_block;
fh16[2] = (__u16)ei->i_iget5_offset; /* fh16 [sic] */
+ fh16[3] = 0; /* avoid leaking uninitialized data */
fh32[2] = inode->i_generation;
- if (connectable && !S_ISDIR(inode->i_mode)) {
- struct inode *parent;
+ if (parent) {
struct iso_inode_info *eparent;
- spin_lock(&dentry->d_lock);
- parent = dentry->d_parent->d_inode;
eparent = ISOFS_I(parent);
fh32[3] = eparent->i_iget5_block;
fh16[3] = (__u16)eparent->i_iget5_offset; /* fh16 [sic] */
fh32[4] = parent->i_generation;
- spin_unlock(&dentry->d_lock);
len = 5;
type = 2;
}
@@ -179,7 +175,7 @@ static struct dentry *isofs_fh_to_parent(struct super_block *sb,
{
struct isofs_fid *ifid = (struct isofs_fid *)fid;
- if (fh_type != 2)
+ if (fh_len < 2 || fh_type != 2)
return NULL;
return isofs_export_iget(sb,
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index bd62c76fb5d..4556ce1af5b 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -21,37 +21,30 @@
#include <linux/cdrom.h>
#include <linux/parser.h>
#include <linux/mpage.h>
+#include <linux/user_namespace.h>
#include "isofs.h"
#include "zisofs.h"
#define BEQUIET
-static int isofs_hashi(const struct dentry *parent, const struct inode *inode,
- struct qstr *qstr);
-static int isofs_hash(const struct dentry *parent, const struct inode *inode,
- struct qstr *qstr);
+static int isofs_hashi(const struct dentry *parent, struct qstr *qstr);
+static int isofs_hash(const struct dentry *parent, struct qstr *qstr);
static int isofs_dentry_cmpi(const struct dentry *parent,
- const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
+ const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name);
static int isofs_dentry_cmp(const struct dentry *parent,
- const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
+ const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name);
#ifdef CONFIG_JOLIET
-static int isofs_hashi_ms(const struct dentry *parent, const struct inode *inode,
- struct qstr *qstr);
-static int isofs_hash_ms(const struct dentry *parent, const struct inode *inode,
- struct qstr *qstr);
+static int isofs_hashi_ms(const struct dentry *parent, struct qstr *qstr);
+static int isofs_hash_ms(const struct dentry *parent, struct qstr *qstr);
static int isofs_dentry_cmpi_ms(const struct dentry *parent,
- const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
+ const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name);
static int isofs_dentry_cmp_ms(const struct dentry *parent,
- const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
+ const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name);
#endif
@@ -100,7 +93,7 @@ static void init_once(void *foo)
inode_init_once(&ei->vfs_inode);
}
-static int init_inodecache(void)
+static int __init init_inodecache(void)
{
isofs_inode_cachep = kmem_cache_create("isofs_inode_cache",
sizeof(struct iso_inode_info),
@@ -114,13 +107,19 @@ static int init_inodecache(void)
static void destroy_inodecache(void)
{
+ /*
+ * Make sure all delayed rcu free inodes are flushed before we
+ * destroy cache.
+ */
+ rcu_barrier();
kmem_cache_destroy(isofs_inode_cachep);
}
static int isofs_remount(struct super_block *sb, int *flags, char *data)
{
- /* we probably want a lot more here */
- *flags |= MS_RDONLY;
+ sync_filesystem(sb);
+ if (!(*flags & MS_RDONLY))
+ return -EROFS;
return 0;
}
@@ -171,8 +170,8 @@ struct iso9660_options{
unsigned int blocksize;
umode_t fmode;
umode_t dmode;
- gid_t gid;
- uid_t uid;
+ kgid_t gid;
+ kuid_t uid;
char *iocharset;
/* LVE */
s32 session;
@@ -183,7 +182,7 @@ struct iso9660_options{
* Compute the hash for the isofs name corresponding to the dentry.
*/
static int
-isofs_hash_common(const struct dentry *dentry, struct qstr *qstr, int ms)
+isofs_hash_common(struct qstr *qstr, int ms)
{
const char *name;
int len;
@@ -204,7 +203,7 @@ isofs_hash_common(const struct dentry *dentry, struct qstr *qstr, int ms)
* Compute the hash for the isofs name corresponding to the dentry.
*/
static int
-isofs_hashi_common(const struct dentry *dentry, struct qstr *qstr, int ms)
+isofs_hashi_common(struct qstr *qstr, int ms)
{
const char *name;
int len;
@@ -259,30 +258,26 @@ static int isofs_dentry_cmp_common(
}
static int
-isofs_hash(const struct dentry *dentry, const struct inode *inode,
- struct qstr *qstr)
+isofs_hash(const struct dentry *dentry, struct qstr *qstr)
{
- return isofs_hash_common(dentry, qstr, 0);
+ return isofs_hash_common(qstr, 0);
}
static int
-isofs_hashi(const struct dentry *dentry, const struct inode *inode,
- struct qstr *qstr)
+isofs_hashi(const struct dentry *dentry, struct qstr *qstr)
{
- return isofs_hashi_common(dentry, qstr, 0);
+ return isofs_hashi_common(qstr, 0);
}
static int
-isofs_dentry_cmp(const struct dentry *parent, const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
+isofs_dentry_cmp(const struct dentry *parent, const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
return isofs_dentry_cmp_common(len, str, name, 0, 0);
}
static int
-isofs_dentry_cmpi(const struct dentry *parent, const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
+isofs_dentry_cmpi(const struct dentry *parent, const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
return isofs_dentry_cmp_common(len, str, name, 0, 1);
@@ -290,30 +285,26 @@ isofs_dentry_cmpi(const struct dentry *parent, const struct inode *pinode,
#ifdef CONFIG_JOLIET
static int
-isofs_hash_ms(const struct dentry *dentry, const struct inode *inode,
- struct qstr *qstr)
+isofs_hash_ms(const struct dentry *dentry, struct qstr *qstr)
{
- return isofs_hash_common(dentry, qstr, 1);
+ return isofs_hash_common(qstr, 1);
}
static int
-isofs_hashi_ms(const struct dentry *dentry, const struct inode *inode,
- struct qstr *qstr)
+isofs_hashi_ms(const struct dentry *dentry, struct qstr *qstr)
{
- return isofs_hashi_common(dentry, qstr, 1);
+ return isofs_hashi_common(qstr, 1);
}
static int
-isofs_dentry_cmp_ms(const struct dentry *parent, const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
+isofs_dentry_cmp_ms(const struct dentry *parent, const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
return isofs_dentry_cmp_common(len, str, name, 1, 0);
}
static int
-isofs_dentry_cmpi_ms(const struct dentry *parent, const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
+isofs_dentry_cmpi_ms(const struct dentry *parent, const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
return isofs_dentry_cmp_common(len, str, name, 1, 1);
@@ -383,8 +374,8 @@ static int parse_options(char *options, struct iso9660_options *popt)
popt->fmode = popt->dmode = ISOFS_INVALID_MODE;
popt->uid_set = 0;
popt->gid_set = 0;
- popt->gid = 0;
- popt->uid = 0;
+ popt->gid = GLOBAL_ROOT_GID;
+ popt->uid = GLOBAL_ROOT_UID;
popt->iocharset = NULL;
popt->utf8 = 0;
popt->overriderockperm = 0;
@@ -460,13 +451,17 @@ static int parse_options(char *options, struct iso9660_options *popt)
case Opt_uid:
if (match_int(&args[0], &option))
return 0;
- popt->uid = option;
+ popt->uid = make_kuid(current_user_ns(), option);
+ if (!uid_valid(popt->uid))
+ return 0;
popt->uid_set = 1;
break;
case Opt_gid:
if (match_int(&args[0], &option))
return 0;
- popt->gid = option;
+ popt->gid = make_kgid(current_user_ns(), option);
+ if (!gid_valid(popt->gid))
+ return 0;
popt->gid_set = 1;
break;
case Opt_mode:
@@ -769,15 +764,6 @@ root_found:
*/
s->s_maxbytes = 0x80000000000LL;
- /*
- * The CDROM is read-only, has no nodes (devices) on it, and since
- * all of the files appear to be owned by root, we really do not want
- * to allow suid. (suid or devices will not show up unless we have
- * Rock Ridge extensions)
- */
-
- s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
-
/* Set this for reference. Its not currently used except on write
which we don't have .. */
@@ -947,9 +933,8 @@ root_found:
s->s_d_op = &isofs_dentry_ops[table];
/* get the root dentry */
- s->s_root = d_alloc_root(inode);
+ s->s_root = d_make_root(inode);
if (!(s->s_root)) {
- iput(inode);
error = -ENOMEM;
goto out_no_inode;
}
@@ -1537,6 +1522,9 @@ struct inode *isofs_iget(struct super_block *sb,
static struct dentry *isofs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
+ /* We don't support read-write mounts */
+ if (!(flags & MS_RDONLY))
+ return ERR_PTR(-EACCES);
return mount_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
}
@@ -1547,6 +1535,8 @@ static struct file_system_type iso9660_fs_type = {
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
+MODULE_ALIAS_FS("iso9660");
+MODULE_ALIAS("iso9660");
static int __init init_iso9660_fs(void)
{
@@ -1584,5 +1574,3 @@ static void __exit exit_iso9660_fs(void)
module_init(init_iso9660_fs)
module_exit(exit_iso9660_fs)
MODULE_LICENSE("GPL");
-/* Actual filesystem name is iso9660, as requested in filesystems.c */
-MODULE_ALIAS("iso9660");
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index 0e73f63d927..99167238518 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -52,8 +52,8 @@ struct isofs_sb_info {
umode_t s_fmode;
umode_t s_dmode;
- gid_t s_gid;
- uid_t s_uid;
+ kgid_t s_gid;
+ kuid_t s_uid;
struct nls_table *s_nls_iocharset; /* Native language support table */
};
@@ -114,7 +114,7 @@ extern int isofs_name_translate(struct iso_directory_record *, char *, struct in
int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *);
int get_acorn_filename(struct iso_directory_record *, char *, struct inode *);
-extern struct dentry *isofs_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *isofs_lookup(struct inode *, struct dentry *, unsigned int flags);
extern struct buffer_head *isofs_bread(struct inode *, sector_t);
extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long);
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 1e2946f2a69..95295640d9c 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -37,8 +37,7 @@ isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
qstr.name = compare;
qstr.len = dlen;
- return dentry->d_op->d_compare(NULL, NULL, NULL, NULL,
- dentry->d_name.len, dentry->d_name.name, &qstr);
+ return dentry->d_op->d_compare(NULL, NULL, dentry->d_name.len, dentry->d_name.name, &qstr);
}
/*
@@ -163,7 +162,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
return 0;
}
-struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
{
int found;
unsigned long uninitialized_var(block);
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 70e79d0c756..c0bf42472e4 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -364,8 +364,8 @@ repeat:
case SIG('P', 'X'):
inode->i_mode = isonum_733(rr->u.PX.mode);
set_nlink(inode, isonum_733(rr->u.PX.n_links));
- inode->i_uid = isonum_733(rr->u.PX.uid);
- inode->i_gid = isonum_733(rr->u.PX.gid);
+ i_uid_write(inode, isonum_733(rr->u.PX.uid));
+ i_gid_write(inode, isonum_733(rr->u.PX.gid));
break;
case SIG('P', 'N'):
{