fix some file modes in calls to withTmpFileIn to honor umask
Also audited for other calls to openTempFile, and all are ok, except for viaTmp which will need further work. Remote.Directory fixed to set umask mode when writing to an export, although it has another one using viaTmp that's not fixed. Will make exports that are published via a http server running as another user work, for example. Remote.BitTorrent fixed to set umask mode when downloading the torrent file. Normally this does not matter as that file does not hang around after the download, but if a bittorrent download were started by one user, got interrupted and then another user ran it, this will let them access the torrent file created by the first user.
This commit is contained in:
parent
5a9f518a42
commit
eed20fe3b7
5 changed files with 51 additions and 7 deletions
|
@ -9,6 +9,7 @@ module Annex.Perms (
|
||||||
FileMode,
|
FileMode,
|
||||||
setAnnexFilePerm,
|
setAnnexFilePerm,
|
||||||
setAnnexDirPerm,
|
setAnnexDirPerm,
|
||||||
|
resetAnnexFilePerm,
|
||||||
annexFileMode,
|
annexFileMode,
|
||||||
createAnnexDirectory,
|
createAnnexDirectory,
|
||||||
createWorkTreeDirectory,
|
createWorkTreeDirectory,
|
||||||
|
@ -42,23 +43,49 @@ setAnnexDirPerm = setAnnexPerm True
|
||||||
|
|
||||||
{- Sets appropriate file mode for a file or directory in the annex,
|
{- Sets appropriate file mode for a file or directory in the annex,
|
||||||
- other than the content files and content directory. Normally,
|
- other than the content files and content directory. Normally,
|
||||||
- use the default mode, but with core.sharedRepository set,
|
- don't change the mode, but with core.sharedRepository set,
|
||||||
- allow the group to write, etc. -}
|
- allow the group to write, etc. -}
|
||||||
setAnnexPerm :: Bool -> FilePath -> Annex ()
|
setAnnexPerm :: Bool -> FilePath -> Annex ()
|
||||||
setAnnexPerm isdir file = unlessM crippledFileSystem $
|
setAnnexPerm = setAnnexPerm' Nothing
|
||||||
|
|
||||||
|
setAnnexPerm' :: Maybe ([FileMode] -> FileMode -> FileMode) -> Bool -> FilePath -> Annex ()
|
||||||
|
setAnnexPerm' modef isdir file = unlessM crippledFileSystem $
|
||||||
withShared $ liftIO . go
|
withShared $ liftIO . go
|
||||||
where
|
where
|
||||||
go GroupShared = void $ tryIO $ modifyFileMode file $ addModes $
|
go GroupShared = void $ tryIO $ modifyFileMode file $ modef' $
|
||||||
groupSharedModes ++
|
groupSharedModes ++
|
||||||
if isdir then [ ownerExecuteMode, groupExecuteMode ] else []
|
if isdir then [ ownerExecuteMode, groupExecuteMode ] else []
|
||||||
go AllShared = void $ tryIO $ modifyFileMode file $ addModes $
|
go AllShared = void $ tryIO $ modifyFileMode file $ modef' $
|
||||||
readModes ++
|
readModes ++
|
||||||
[ ownerWriteMode, groupWriteMode ] ++
|
[ ownerWriteMode, groupWriteMode ] ++
|
||||||
if isdir then executeModes else []
|
if isdir then executeModes else []
|
||||||
go _ = noop
|
go _ = case modef of
|
||||||
|
Nothing -> noop
|
||||||
|
Just f -> void $ tryIO $
|
||||||
|
modifyFileMode file $ f []
|
||||||
|
modef' = fromMaybe addModes modef
|
||||||
|
|
||||||
|
resetAnnexFilePerm :: FilePath -> Annex ()
|
||||||
|
resetAnnexFilePerm = resetAnnexPerm False
|
||||||
|
|
||||||
|
{- Like setAnnexPerm, but ignores the current mode of the file entirely,
|
||||||
|
- and sets the same mode that the umask would result in when creating a
|
||||||
|
- new file.
|
||||||
|
-
|
||||||
|
- Useful eg, after creating a temporary file with locked down modes,
|
||||||
|
- which is going to be moved to a non-temporary location and needs
|
||||||
|
- usual modes.
|
||||||
|
-}
|
||||||
|
resetAnnexPerm :: Bool -> FilePath -> Annex ()
|
||||||
|
resetAnnexPerm isdir file = unlessM crippledFileSystem $ do
|
||||||
|
defmode <- liftIO defaultFileMode
|
||||||
|
let modef moremodes _oldmode = addModes moremodes defmode
|
||||||
|
setAnnexPerm' (Just modef) isdir file
|
||||||
|
|
||||||
{- Gets the appropriate mode to use for creating a file in the annex
|
{- Gets the appropriate mode to use for creating a file in the annex
|
||||||
- (other than content files, which are locked down more). -}
|
- (other than content files, which are locked down more). The umask is not
|
||||||
|
- taken into account; this is for use with actions that create the file
|
||||||
|
- and apply the umask automatically. -}
|
||||||
annexFileMode :: Annex FileMode
|
annexFileMode :: Annex FileMode
|
||||||
annexFileMode = withShared $ return . go
|
annexFileMode = withShared $ return . go
|
||||||
where
|
where
|
||||||
|
|
|
@ -202,6 +202,7 @@ downloadTorrentFile u = do
|
||||||
else withOtherTmp $ \othertmp -> do
|
else withOtherTmp $ \othertmp -> do
|
||||||
withTmpFileIn othertmp "torrent" $ \f h -> do
|
withTmpFileIn othertmp "torrent" $ \f h -> do
|
||||||
liftIO $ hClose h
|
liftIO $ hClose h
|
||||||
|
resetAnnexFilePerm f
|
||||||
ok <- Url.withUrlOptions $
|
ok <- Url.withUrlOptions $
|
||||||
Url.download nullMeterUpdate u f
|
Url.download nullMeterUpdate u f
|
||||||
when ok $
|
when ok $
|
||||||
|
|
|
@ -31,6 +31,7 @@ import Remote.Helper.ExportImport
|
||||||
import Types.Import
|
import Types.Import
|
||||||
import qualified Remote.Directory.LegacyChunked as Legacy
|
import qualified Remote.Directory.LegacyChunked as Legacy
|
||||||
import Annex.Content
|
import Annex.Content
|
||||||
|
import Annex.Perms
|
||||||
import Annex.UUID
|
import Annex.UUID
|
||||||
import Backend
|
import Backend
|
||||||
import Types.KeySource
|
import Types.KeySource
|
||||||
|
@ -436,6 +437,7 @@ storeExportWithContentIdentifierM dir src _k loc overwritablecids p = do
|
||||||
liftIO $ withMeteredFile src p (L.hPut tmph)
|
liftIO $ withMeteredFile src p (L.hPut tmph)
|
||||||
liftIO $ hFlush tmph
|
liftIO $ hFlush tmph
|
||||||
liftIO $ hClose tmph
|
liftIO $ hClose tmph
|
||||||
|
resetAnnexFilePerm tmpf
|
||||||
liftIO (getFileStatus tmpf) >>= liftIO . mkContentIdentifier tmpf >>= \case
|
liftIO (getFileStatus tmpf) >>= liftIO . mkContentIdentifier tmpf >>= \case
|
||||||
Nothing -> giveup "unable to generate content identifier"
|
Nothing -> giveup "unable to generate content identifier"
|
||||||
Just newcid -> do
|
Just newcid -> do
|
||||||
|
|
|
@ -30,6 +30,10 @@ type Template = String
|
||||||
{- Runs an action like writeFile, writing to a temp file first and
|
{- Runs an action like writeFile, writing to a temp file first and
|
||||||
- then moving it into place. The temp file is stored in the same
|
- then moving it into place. The temp file is stored in the same
|
||||||
- directory as the final file to avoid cross-device renames.
|
- directory as the final file to avoid cross-device renames.
|
||||||
|
-
|
||||||
|
- Note that the tmp file will have a file mode that only allows the
|
||||||
|
- current user to access it. The write action can change the mode
|
||||||
|
- to whatever is desired.
|
||||||
-}
|
-}
|
||||||
viaTmp :: (MonadMask m, MonadIO m) => (FilePath -> v -> m ()) -> FilePath -> v -> m ()
|
viaTmp :: (MonadMask m, MonadIO m) => (FilePath -> v -> m ()) -> FilePath -> v -> m ()
|
||||||
viaTmp a file content = bracketIO setup cleanup use
|
viaTmp a file content = bracketIO setup cleanup use
|
||||||
|
@ -55,7 +59,11 @@ withTmpFile template a = do
|
||||||
withTmpFileIn tmpdir template a
|
withTmpFileIn tmpdir template a
|
||||||
|
|
||||||
{- Runs an action with a tmp file located in the specified directory,
|
{- Runs an action with a tmp file located in the specified directory,
|
||||||
- then removes the file. -}
|
- then removes the file.
|
||||||
|
-
|
||||||
|
- Note that the tmp file will have a file mode that only allows the
|
||||||
|
- current user to access it.
|
||||||
|
-}
|
||||||
withTmpFileIn :: (MonadIO m, MonadMask m) => FilePath -> Template -> (FilePath -> Handle -> m a) -> m a
|
withTmpFileIn :: (MonadIO m, MonadMask m) => FilePath -> Template -> (FilePath -> Handle -> m a) -> m a
|
||||||
withTmpFileIn tmpdir template a = bracket create remove use
|
withTmpFileIn tmpdir template a = bracket create remove use
|
||||||
where
|
where
|
||||||
|
|
|
@ -11,5 +11,11 @@ init, and some stuff in ~/.config/git-annex like autostart.
|
||||||
`withTmpFileIn` also uses openTempFile, and probably its callers do need to
|
`withTmpFileIn` also uses openTempFile, and probably its callers do need to
|
||||||
adjust perms if desired since it could be used with a real temp directory.
|
adjust perms if desired since it could be used with a real temp directory.
|
||||||
|
|
||||||
|
> Audited and fixed these. It affected only directory special remote and
|
||||||
|
> bittorrent special remote if a download from it were interrupted and then
|
||||||
|
> resumed by a different user than the one who started it. --[[Joey]]
|
||||||
|
|
||||||
There are also a couple of other uses of openTempFile, which need to be
|
There are also a couple of other uses of openTempFile, which need to be
|
||||||
audited for this problem. --[[Joey]]
|
audited for this problem. --[[Joey]]
|
||||||
|
|
||||||
|
> Checked, all were ok. --[[Joey]]
|
||||||
|
|
Loading…
Reference in a new issue