@@ -60,11 +60,12 @@ typedef struct {
6060 char * name ;
6161 struct dentry * dentry ;
6262 struct file * interp_file ;
63- refcount_t users ; /* sync removal with load_misc_binary() */
6463} Node ;
6564
6665static DEFINE_RWLOCK (entries_lock );
6766static struct file_system_type bm_fs_type ;
67+ static struct vfsmount * bm_mnt ;
68+ static int entry_count ;
6869
6970/*
7071 * Max length of the register string. Determined by:
@@ -81,23 +82,19 @@ static struct file_system_type bm_fs_type;
8182 */
8283#define MAX_REGISTER_LENGTH 1920
8384
84- /**
85- * search_binfmt_handler - search for a binary handler for @bprm
86- * @misc: handle to binfmt_misc instance
87- * @bprm: binary for which we are looking for a handler
88- *
89- * Search for a binary type handler for @bprm in the list of registered binary
90- * type handlers.
91- *
92- * Return: binary type list entry on success, NULL on failure
85+ /*
86+ * Check if we support the binfmt
87+ * if we do, return the node, else NULL
88+ * locking is done in load_misc_binary
9389 */
94- static Node * search_binfmt_handler (struct linux_binprm * bprm )
90+ static Node * check_file (struct linux_binprm * bprm )
9591{
9692 char * p = strrchr (bprm -> interp , '.' );
97- Node * e ;
93+ struct list_head * l ;
9894
9995 /* Walk all the registered handlers. */
100- list_for_each_entry (e , & entries , list ) {
96+ list_for_each (l , & entries ) {
97+ Node * e = list_entry (l , Node , list );
10198 char * s ;
10299 int j ;
103100
@@ -126,49 +123,9 @@ static Node *search_binfmt_handler(struct linux_binprm *bprm)
126123 if (j == e -> size )
127124 return e ;
128125 }
129-
130126 return NULL ;
131127}
132128
133- /**
134- * get_binfmt_handler - try to find a binary type handler
135- * @misc: handle to binfmt_misc instance
136- * @bprm: binary for which we are looking for a handler
137- *
138- * Try to find a binfmt handler for the binary type. If one is found take a
139- * reference to protect against removal via bm_{entry,status}_write().
140- *
141- * Return: binary type list entry on success, NULL on failure
142- */
143- static Node * get_binfmt_handler (struct linux_binprm * bprm )
144- {
145- Node * e ;
146-
147- read_lock (& entries_lock );
148- e = search_binfmt_handler (bprm );
149- if (e )
150- refcount_inc (& e -> users );
151- read_unlock (& entries_lock );
152- return e ;
153- }
154-
155- /**
156- * put_binfmt_handler - put binary handler node
157- * @e: node to put
158- *
159- * Free node syncing with load_misc_binary() and defer final free to
160- * load_misc_binary() in case it is using the binary type handler we were
161- * requested to remove.
162- */
163- static void put_binfmt_handler (Node * e )
164- {
165- if (refcount_dec_and_test (& e -> users )) {
166- if (e -> flags & MISC_FMT_OPEN_FILE )
167- filp_close (e -> interp_file , NULL );
168- kfree (e );
169- }
170- }
171-
172129/*
173130 * the loader itself
174131 */
@@ -182,7 +139,12 @@ static int load_misc_binary(struct linux_binprm *bprm)
182139 if (!enabled )
183140 return retval ;
184141
185- fmt = get_binfmt_handler (bprm );
142+ /* to keep locking time low, we copy the interpreter string */
143+ read_lock (& entries_lock );
144+ fmt = check_file (bprm );
145+ if (fmt )
146+ dget (fmt -> dentry );
147+ read_unlock (& entries_lock );
186148 if (!fmt )
187149 return retval ;
188150
@@ -236,16 +198,7 @@ static int load_misc_binary(struct linux_binprm *bprm)
236198
237199 retval = 0 ;
238200ret :
239-
240- /*
241- * If we actually put the node here all concurrent calls to
242- * load_misc_binary() will have finished. We also know
243- * that for the refcount to be zero ->evict_inode() must have removed
244- * the node to be deleted from the list. All that is left for us is to
245- * close and free.
246- */
247- put_binfmt_handler (fmt );
248-
201+ dput (fmt -> dentry );
249202 return retval ;
250203}
251204
@@ -600,90 +553,30 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
600553 return inode ;
601554}
602555
603- /**
604- * bm_evict_inode - cleanup data associated with @inode
605- * @inode: inode to which the data is attached
606- *
607- * Cleanup the binary type handler data associated with @inode if a binary type
608- * entry is removed or the filesystem is unmounted and the super block is
609- * shutdown.
610- *
611- * If the ->evict call was not caused by a super block shutdown but by a write
612- * to remove the entry or all entries via bm_{entry,status}_write() the entry
613- * will have already been removed from the list. We keep the list_empty() check
614- * to make that explicit.
615- */
616556static void bm_evict_inode (struct inode * inode )
617557{
618558 Node * e = inode -> i_private ;
619559
620- clear_inode (inode );
560+ if (e && e -> flags & MISC_FMT_OPEN_FILE )
561+ filp_close (e -> interp_file , NULL );
621562
622- if (e ) {
623- write_lock (& entries_lock );
624- if (!list_empty (& e -> list ))
625- list_del_init (& e -> list );
626- write_unlock (& entries_lock );
627- put_binfmt_handler (e );
628- }
563+ clear_inode (inode );
564+ kfree (e );
629565}
630566
631- /**
632- * unlink_binfmt_dentry - remove the dentry for the binary type handler
633- * @dentry: dentry associated with the binary type handler
634- *
635- * Do the actual filesystem work to remove a dentry for a registered binary
636- * type handler. Since binfmt_misc only allows simple files to be created
637- * directly under the root dentry of the filesystem we ensure that we are
638- * indeed passed a dentry directly beneath the root dentry, that the inode
639- * associated with the root dentry is locked, and that it is a regular file we
640- * are asked to remove.
641- */
642- static void unlink_binfmt_dentry (struct dentry * dentry )
567+ static void kill_node (Node * e )
643568{
644- struct dentry * parent = dentry -> d_parent ;
645- struct inode * inode , * parent_inode ;
646-
647- /* All entries are immediate descendants of the root dentry. */
648- if (WARN_ON_ONCE (dentry -> d_sb -> s_root != parent ))
649- return ;
650-
651- /* We only expect to be called on regular files. */
652- inode = d_inode (dentry );
653- if (WARN_ON_ONCE (!S_ISREG (inode -> i_mode )))
654- return ;
655-
656- /* The parent inode must be locked. */
657- parent_inode = d_inode (parent );
658- if (WARN_ON_ONCE (!inode_is_locked (parent_inode )))
659- return ;
660-
661- if (simple_positive (dentry )) {
662- dget (dentry );
663- simple_unlink (parent_inode , dentry );
664- d_delete (dentry );
665- dput (dentry );
666- }
667- }
569+ struct dentry * dentry ;
668570
669- /**
670- * remove_binfmt_handler - remove a binary type handler
671- * @misc: handle to binfmt_misc instance
672- * @e: binary type handler to remove
673- *
674- * Remove a binary type handler from the list of binary type handlers and
675- * remove its associated dentry. This is called from
676- * binfmt_{entry,status}_write(). In the future, we might want to think about
677- * adding a proper ->unlink() method to binfmt_misc instead of forcing caller's
678- * to use writes to files in order to delete binary type handlers. But it has
679- * worked for so long that it's not a pressing issue.
680- */
681- static void remove_binfmt_handler (Node * e )
682- {
683571 write_lock (& entries_lock );
684572 list_del_init (& e -> list );
685573 write_unlock (& entries_lock );
686- unlink_binfmt_dentry (e -> dentry );
574+
575+ dentry = e -> dentry ;
576+ drop_nlink (d_inode (dentry ));
577+ d_drop (dentry );
578+ dput (dentry );
579+ simple_release_fs (& bm_mnt , & entry_count );
687580}
688581
689582/* /<entry> */
@@ -710,8 +603,8 @@ bm_entry_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
710603static ssize_t bm_entry_write (struct file * file , const char __user * buffer ,
711604 size_t count , loff_t * ppos )
712605{
713- struct inode * inode = file_inode ( file ) ;
714- Node * e = inode -> i_private ;
606+ struct dentry * root ;
607+ Node * e = file_inode ( file ) -> i_private ;
715608 int res = parse_command (buffer , count );
716609
717610 switch (res ) {
@@ -725,22 +618,13 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
725618 break ;
726619 case 3 :
727620 /* Delete this handler. */
728- inode = d_inode ( inode -> i_sb -> s_root ) ;
729- inode_lock (inode );
621+ root = file_inode ( file ) -> i_sb -> s_root ;
622+ inode_lock (d_inode ( root ) );
730623
731- /*
732- * In order to add new element or remove elements from the list
733- * via bm_{entry,register,status}_write() inode_lock() on the
734- * root inode must be held.
735- * The lock is exclusive ensuring that the list can't be
736- * modified. Only load_misc_binary() can access but does so
737- * read-only. So we only need to take the write lock when we
738- * actually remove the entry from the list.
739- */
740624 if (!list_empty (& e -> list ))
741- remove_binfmt_handler (e );
625+ kill_node (e );
742626
743- inode_unlock (inode );
627+ inode_unlock (d_inode ( root ) );
744628 break ;
745629 default :
746630 return res ;
@@ -799,7 +683,13 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
799683 if (!inode )
800684 goto out2 ;
801685
802- refcount_set (& e -> users , 1 );
686+ err = simple_pin_fs (& bm_fs_type , & bm_mnt , & entry_count );
687+ if (err ) {
688+ iput (inode );
689+ inode = NULL ;
690+ goto out2 ;
691+ }
692+
803693 e -> dentry = dget (dentry );
804694 inode -> i_private = e ;
805695 inode -> i_fop = & bm_entry_operations ;
@@ -843,8 +733,7 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer,
843733 size_t count , loff_t * ppos )
844734{
845735 int res = parse_command (buffer , count );
846- Node * e , * next ;
847- struct inode * inode ;
736+ struct dentry * root ;
848737
849738 switch (res ) {
850739 case 1 :
@@ -857,22 +746,13 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer,
857746 break ;
858747 case 3 :
859748 /* Delete all handlers. */
860- inode = d_inode ( file_inode (file )-> i_sb -> s_root ) ;
861- inode_lock (inode );
749+ root = file_inode (file )-> i_sb -> s_root ;
750+ inode_lock (d_inode ( root ) );
862751
863- /*
864- * In order to add new element or remove elements from the list
865- * via bm_{entry,register,status}_write() inode_lock() on the
866- * root inode must be held.
867- * The lock is exclusive ensuring that the list can't be
868- * modified. Only load_misc_binary() can access but does so
869- * read-only. So we only need to take the write lock when we
870- * actually remove the entry from the list.
871- */
872- list_for_each_entry_safe (e , next , & entries , list )
873- remove_binfmt_handler (e );
752+ while (!list_empty (& entries ))
753+ kill_node (list_first_entry (& entries , Node , list ));
874754
875- inode_unlock (inode );
755+ inode_unlock (d_inode ( root ) );
876756 break ;
877757 default :
878758 return res ;
0 commit comments