MCPcopy
hub / github.com/apptainer/apptainer / Open

Method Open

internal/pkg/util/crypt/crypt_dev.go:283–357  ·  view source on GitHub ↗

Open opens the encrypted filesystem specified by path (usually a loop device, but any encrypted block device will do) using the given key and returns the name assigned to it that can be later used to close the device.

(key []byte, path string)

Source from the content-addressed store, hash-verified

281// and returns the name assigned to it that can be later used to close
282// the device.
283func (crypt *Device) Open(key []byte, path string) (string, error) {
284 fd, err := lock.Exclusive("/dev/mapper")
285 if err != nil {
286 return "", fmt.Errorf("unable to acquire lock on /dev/mapper")
287 }
288 defer lock.Release(fd)
289
290 maxRetries := 3 // Arbitrary number of retries.
291
292 cryptsetup, err := bin.FindBin("cryptsetup")
293 if err != nil {
294 return "", err
295 }
296 if !fs.IsOwner(cryptsetup, 0) {
297 return "", fmt.Errorf("%s must be owned by root", cryptsetup)
298 }
299
300 for i := 0; i < maxRetries; i++ {
301 nextCrypt, err := getNextAvailableCryptDevice()
302 if err != nil {
303 return "", fmt.Errorf("while getting next device: %v", err)
304 }
305 if nextCrypt == "" {
306 return "", errors.New("сrypt device not available")
307 }
308
309 cmd := exec.Command(cryptsetup, "open", "--batch-mode", "--type", "luks2", "--key-file", "-", path, nextCrypt)
310 cmd.SysProcAttr = &syscall.SysProcAttr{}
311 cmd.SysProcAttr.Credential = &syscall.Credential{Uid: 0, Gid: 0}
312 sylog.Debugf("Running %s %s", cmd.Path, strings.Join(cmd.Args, " "))
313
314 cmd.Stdin = bytes.NewBuffer(key)
315 out, err := cmd.CombinedOutput()
316 if err != nil {
317 if strings.Contains(string(out), "Device already exists") {
318 continue
319 }
320 err = checkCryptsetupVersion(cryptsetup)
321 if err == ErrUnsupportedCryptsetupVersion {
322 // Special case of unsupported version of cryptsetup. We return the raw error
323 // so it can propagate up and a user-friendly message be displayed. This error
324 // should trigger an error at the CLI level.
325 return "", err
326 }
327
328 if strings.Contains(string(out), "No key available") {
329 sylog.Debugf("Invalid password")
330 return "", ErrInvalidPassphrase
331 }
332
333 return "", fmt.Errorf("cryptsetup open failed: %s: %v", string(out), err)
334 }
335
336 for attempt := 0; true; attempt++ {
337 _, err := os.Stat("/dev/mapper/" + nextCrypt)
338 if err == nil {
339 break
340 }

Callers 15

DecryptMethod · 0.95
EncryptFilesystemMethod · 0.95
TestEncryptFunction · 0.95
ext3InitializerTestFunction · 0.80
TestCheckExt3HeaderFunction · 0.80
TestInitializerFunction · 0.80
TestCheckSquashfsHeaderFunction · 0.80
TestSquashfsInitializerFunction · 0.80
EnterFunction · 0.80
IsInsideUserNamespaceFunction · 0.80
getHostIDFunction · 0.80

Calls 8

ExclusiveFunction · 0.92
ReleaseFunction · 0.92
FindBinFunction · 0.92
IsOwnerFunction · 0.92
DebugfFunction · 0.92
checkCryptsetupVersionFunction · 0.85
StatMethod · 0.65

Tested by 15

TestEncryptFunction · 0.76
ext3InitializerTestFunction · 0.64
TestCheckExt3HeaderFunction · 0.64
TestInitializerFunction · 0.64
TestCheckSquashfsHeaderFunction · 0.64
TestSquashfsInitializerFunction · 0.64
TestLoopFunction · 0.64
TestByteRangeFunction · 0.64
ensureIntFunction · 0.64
ensureContainsIntFunction · 0.64
ensureStateBecomesFunction · 0.64